32167 lines
1.6 MiB
32167 lines
1.6 MiB
(function (exports, Laya) {
|
||
'use strict';
|
||
|
||
class MathUtils3D {
|
||
constructor() {
|
||
}
|
||
static isZero(v) {
|
||
return Math.abs(v) < MathUtils3D.zeroTolerance;
|
||
}
|
||
static nearEqual(n1, n2) {
|
||
if (MathUtils3D.isZero(n1 - n2))
|
||
return true;
|
||
return false;
|
||
}
|
||
static fastInvSqrt(value) {
|
||
if (MathUtils3D.isZero(value))
|
||
return value;
|
||
return 1.0 / Math.sqrt(value);
|
||
}
|
||
}
|
||
MathUtils3D.zeroTolerance = 1e-6;
|
||
MathUtils3D.MaxValue = 3.40282347e+38;
|
||
MathUtils3D.MinValue = -3.40282347e+38;
|
||
MathUtils3D.Deg2Rad = Math.PI / 180;
|
||
|
||
class Vector2 {
|
||
constructor(x = 0, y = 0) {
|
||
this.x = x;
|
||
this.y = y;
|
||
}
|
||
setValue(x, y) {
|
||
this.x = x;
|
||
this.y = y;
|
||
}
|
||
static scale(a, b, out) {
|
||
out.x = a.x * b;
|
||
out.y = a.y * b;
|
||
}
|
||
fromArray(array, offset = 0) {
|
||
this.x = array[offset + 0];
|
||
this.y = array[offset + 1];
|
||
}
|
||
toArray(array, offset = 0) {
|
||
array[offset + 0] = this.x;
|
||
array[offset + 1] = this.y;
|
||
}
|
||
cloneTo(destObject) {
|
||
var destVector2 = destObject;
|
||
destVector2.x = this.x;
|
||
destVector2.y = this.y;
|
||
}
|
||
static dot(a, b) {
|
||
return (a.x * b.x) + (a.y * b.y);
|
||
}
|
||
static normalize(s, out) {
|
||
var x = s.x, y = s.y;
|
||
var len = x * x + y * y;
|
||
if (len > 0) {
|
||
len = 1 / Math.sqrt(len);
|
||
out.x = x * len;
|
||
out.y = y * len;
|
||
}
|
||
}
|
||
static scalarLength(a) {
|
||
var x = a.x, y = a.y;
|
||
return Math.sqrt(x * x + y * y);
|
||
}
|
||
clone() {
|
||
var destVector2 = new Vector2();
|
||
this.cloneTo(destVector2);
|
||
return destVector2;
|
||
}
|
||
forNativeElement(nativeElements = null) {
|
||
if (nativeElements) {
|
||
this.elements = nativeElements;
|
||
this.elements[0] = this.x;
|
||
this.elements[1] = this.y;
|
||
}
|
||
else {
|
||
this.elements = new Float32Array([this.x, this.y]);
|
||
}
|
||
Vector2.rewriteNumProperty(this, "x", 0);
|
||
Vector2.rewriteNumProperty(this, "y", 1);
|
||
}
|
||
static rewriteNumProperty(proto, name, index) {
|
||
Object["defineProperty"](proto, name, {
|
||
"get": function () {
|
||
return this.elements[index];
|
||
},
|
||
"set": function (v) {
|
||
this.elements[index] = v;
|
||
}
|
||
});
|
||
}
|
||
}
|
||
Vector2.ZERO = new Vector2(0.0, 0.0);
|
||
Vector2.ONE = new Vector2(1.0, 1.0);
|
||
|
||
class Vector4 {
|
||
constructor(x = 0, y = 0, z = 0, w = 0) {
|
||
this.x = x;
|
||
this.y = y;
|
||
this.z = z;
|
||
this.w = w;
|
||
}
|
||
setValue(x, y, z, w) {
|
||
this.x = x;
|
||
this.y = y;
|
||
this.z = z;
|
||
this.w = w;
|
||
}
|
||
fromArray(array, offset = 0) {
|
||
this.x = array[offset + 0];
|
||
this.y = array[offset + 1];
|
||
this.z = array[offset + 2];
|
||
this.w = array[offset + 3];
|
||
}
|
||
toArray(array, offset = 0) {
|
||
array[offset + 0] = this.x;
|
||
array[offset + 1] = this.y;
|
||
array[offset + 2] = this.z;
|
||
array[offset + 3] = this.w;
|
||
}
|
||
cloneTo(destObject) {
|
||
var destVector4 = destObject;
|
||
destVector4.x = this.x;
|
||
destVector4.y = this.y;
|
||
destVector4.z = this.z;
|
||
destVector4.w = this.w;
|
||
}
|
||
clone() {
|
||
var destVector4 = new Vector4();
|
||
this.cloneTo(destVector4);
|
||
return destVector4;
|
||
}
|
||
static lerp(a, b, t, out) {
|
||
var ax = a.x, ay = a.y, az = a.z, aw = a.w;
|
||
out.x = ax + t * (b.x - ax);
|
||
out.y = ay + t * (b.y - ay);
|
||
out.z = az + t * (b.z - az);
|
||
out.w = aw + t * (b.w - aw);
|
||
}
|
||
static transformByM4x4(vector4, m4x4, out) {
|
||
var vx = vector4.x;
|
||
var vy = vector4.y;
|
||
var vz = vector4.z;
|
||
var vw = vector4.w;
|
||
var me = m4x4.elements;
|
||
out.x = vx * me[0] + vy * me[4] + vz * me[8] + vw * me[12];
|
||
out.y = vx * me[1] + vy * me[5] + vz * me[9] + vw * me[13];
|
||
out.z = vx * me[2] + vy * me[6] + vz * me[10] + vw * me[14];
|
||
out.w = vx * me[3] + vy * me[7] + vz * me[11] + vw * me[15];
|
||
}
|
||
static equals(a, b) {
|
||
return MathUtils3D.nearEqual(Math.abs(a.x), Math.abs(b.x)) && MathUtils3D.nearEqual(Math.abs(a.y), Math.abs(b.y)) && MathUtils3D.nearEqual(Math.abs(a.z), Math.abs(b.z)) && MathUtils3D.nearEqual(Math.abs(a.w), Math.abs(b.w));
|
||
}
|
||
length() {
|
||
return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);
|
||
}
|
||
lengthSquared() {
|
||
return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
|
||
}
|
||
static normalize(s, out) {
|
||
var len = s.length();
|
||
if (len > 0) {
|
||
var inverse = 1.0 / len;
|
||
out.x = s.x * inverse;
|
||
out.y = s.y * inverse;
|
||
out.z = s.z * inverse;
|
||
out.w = s.w * inverse;
|
||
}
|
||
}
|
||
static add(a, b, out) {
|
||
out.x = a.x + b.x;
|
||
out.y = a.y + b.y;
|
||
out.z = a.z + b.z;
|
||
out.w = a.w + b.w;
|
||
}
|
||
static subtract(a, b, out) {
|
||
out.x = a.x - b.x;
|
||
out.y = a.y - b.y;
|
||
out.z = a.z - b.z;
|
||
out.w = a.w - b.w;
|
||
}
|
||
static multiply(a, b, out) {
|
||
out.x = a.x * b.x;
|
||
out.y = a.y * b.y;
|
||
out.z = a.z * b.z;
|
||
out.w = a.w * b.w;
|
||
}
|
||
static scale(a, b, out) {
|
||
out.x = a.x * b;
|
||
out.y = a.y * b;
|
||
out.z = a.z * b;
|
||
out.w = a.w * b;
|
||
}
|
||
static Clamp(value, min, max, out) {
|
||
var x = value.x;
|
||
var y = value.y;
|
||
var z = value.z;
|
||
var w = value.w;
|
||
var mineX = min.x;
|
||
var mineY = min.y;
|
||
var mineZ = min.z;
|
||
var mineW = min.w;
|
||
var maxeX = max.x;
|
||
var maxeY = max.y;
|
||
var maxeZ = max.z;
|
||
var maxeW = max.w;
|
||
x = (x > maxeX) ? maxeX : x;
|
||
x = (x < mineX) ? mineX : x;
|
||
y = (y > maxeY) ? maxeY : y;
|
||
y = (y < mineY) ? mineY : y;
|
||
z = (z > maxeZ) ? maxeZ : z;
|
||
z = (z < mineZ) ? mineZ : z;
|
||
w = (w > maxeW) ? maxeW : w;
|
||
w = (w < mineW) ? mineW : w;
|
||
out.x = x;
|
||
out.y = y;
|
||
out.z = z;
|
||
out.w = w;
|
||
}
|
||
static distanceSquared(value1, value2) {
|
||
var x = value1.x - value2.x;
|
||
var y = value1.y - value2.y;
|
||
var z = value1.z - value2.z;
|
||
var w = value1.w - value2.w;
|
||
return (x * x) + (y * y) + (z * z) + (w * w);
|
||
}
|
||
static distance(value1, value2) {
|
||
var x = value1.x - value2.x;
|
||
var y = value1.y - value2.y;
|
||
var z = value1.z - value2.z;
|
||
var w = value1.w - value2.w;
|
||
return Math.sqrt((x * x) + (y * y) + (z * z) + (w * w));
|
||
}
|
||
static dot(a, b) {
|
||
return (a.x * b.x) + (a.y * b.y) + (a.z * b.z) + (a.w * b.w);
|
||
}
|
||
static min(a, b, out) {
|
||
out.x = Math.min(a.x, b.x);
|
||
out.y = Math.min(a.y, b.y);
|
||
out.z = Math.min(a.z, b.z);
|
||
out.w = Math.min(a.w, b.w);
|
||
}
|
||
static max(a, b, out) {
|
||
out.x = Math.max(a.x, b.x);
|
||
out.y = Math.max(a.y, b.y);
|
||
out.z = Math.max(a.z, b.z);
|
||
out.w = Math.max(a.w, b.w);
|
||
}
|
||
forNativeElement(nativeElements = null) {
|
||
if (nativeElements) {
|
||
this.elements = nativeElements;
|
||
this.elements[0] = this.x;
|
||
this.elements[1] = this.y;
|
||
this.elements[2] = this.z;
|
||
this.elements[3] = this.w;
|
||
}
|
||
else {
|
||
this.elements = new Float32Array([this.x, this.y, this.z, this.w]);
|
||
}
|
||
Vector2.rewriteNumProperty(this, "x", 0);
|
||
Vector2.rewriteNumProperty(this, "y", 1);
|
||
Vector2.rewriteNumProperty(this, "z", 2);
|
||
Vector2.rewriteNumProperty(this, "w", 3);
|
||
}
|
||
}
|
||
Vector4.ZERO = new Vector4();
|
||
Vector4.ONE = new Vector4(1.0, 1.0, 1.0, 1.0);
|
||
Vector4.UnitX = new Vector4(1.0, 0.0, 0.0, 0.0);
|
||
Vector4.UnitY = new Vector4(0.0, 1.0, 0.0, 0.0);
|
||
Vector4.UnitZ = new Vector4(0.0, 0.0, 1.0, 0.0);
|
||
Vector4.UnitW = new Vector4(0.0, 0.0, 0.0, 1.0);
|
||
|
||
class Vector3 {
|
||
constructor(x = 0, y = 0, z = 0) {
|
||
this.x = x;
|
||
this.y = y;
|
||
this.z = z;
|
||
}
|
||
static distanceSquared(value1, value2) {
|
||
var x = value1.x - value2.x;
|
||
var y = value1.y - value2.y;
|
||
var z = value1.z - value2.z;
|
||
return (x * x) + (y * y) + (z * z);
|
||
}
|
||
static distance(value1, value2) {
|
||
var x = value1.x - value2.x;
|
||
var y = value1.y - value2.y;
|
||
var z = value1.z - value2.z;
|
||
return Math.sqrt((x * x) + (y * y) + (z * z));
|
||
}
|
||
static min(a, b, out) {
|
||
out.x = Math.min(a.x, b.x);
|
||
out.y = Math.min(a.y, b.y);
|
||
out.z = Math.min(a.z, b.z);
|
||
}
|
||
static max(a, b, out) {
|
||
out.x = Math.max(a.x, b.x);
|
||
out.y = Math.max(a.y, b.y);
|
||
out.z = Math.max(a.z, b.z);
|
||
}
|
||
static transformQuat(source, rotation, out) {
|
||
var x = source.x, y = source.y, z = source.z, qx = rotation.x, qy = rotation.y, qz = rotation.z, qw = rotation.w, ix = qw * x + qy * z - qz * y, iy = qw * y + qz * x - qx * z, iz = qw * z + qx * y - qy * x, iw = -qx * x - qy * y - qz * z;
|
||
out.x = ix * qw + iw * -qx + iy * -qz - iz * -qy;
|
||
out.y = iy * qw + iw * -qy + iz * -qx - ix * -qz;
|
||
out.z = iz * qw + iw * -qz + ix * -qy - iy * -qx;
|
||
}
|
||
static scalarLength(a) {
|
||
var x = a.x, y = a.y, z = a.z;
|
||
return Math.sqrt(x * x + y * y + z * z);
|
||
}
|
||
static scalarLengthSquared(a) {
|
||
var x = a.x, y = a.y, z = a.z;
|
||
return x * x + y * y + z * z;
|
||
}
|
||
static normalize(s, out) {
|
||
var x = s.x, y = s.y, z = s.z;
|
||
var len = x * x + y * y + z * z;
|
||
if (len > 0) {
|
||
len = 1 / Math.sqrt(len);
|
||
out.x = x * len;
|
||
out.y = y * len;
|
||
out.z = z * len;
|
||
}
|
||
}
|
||
static multiply(a, b, out) {
|
||
out.x = a.x * b.x;
|
||
out.y = a.y * b.y;
|
||
out.z = a.z * b.z;
|
||
}
|
||
static scale(a, b, out) {
|
||
out.x = a.x * b;
|
||
out.y = a.y * b;
|
||
out.z = a.z * b;
|
||
}
|
||
static lerp(a, b, t, out) {
|
||
var ax = a.x, ay = a.y, az = a.z;
|
||
out.x = ax + t * (b.x - ax);
|
||
out.y = ay + t * (b.y - ay);
|
||
out.z = az + t * (b.z - az);
|
||
}
|
||
static transformV3ToV3(vector, transform, result) {
|
||
var intermediate = Vector3._tempVector4;
|
||
Vector3.transformV3ToV4(vector, transform, intermediate);
|
||
result.x = intermediate.x;
|
||
result.y = intermediate.y;
|
||
result.z = intermediate.z;
|
||
}
|
||
static transformV3ToV4(vector, transform, result) {
|
||
var vectorX = vector.x;
|
||
var vectorY = vector.y;
|
||
var vectorZ = vector.z;
|
||
var transformElem = transform.elements;
|
||
result.x = (vectorX * transformElem[0]) + (vectorY * transformElem[4]) + (vectorZ * transformElem[8]) + transformElem[12];
|
||
result.y = (vectorX * transformElem[1]) + (vectorY * transformElem[5]) + (vectorZ * transformElem[9]) + transformElem[13];
|
||
result.z = (vectorX * transformElem[2]) + (vectorY * transformElem[6]) + (vectorZ * transformElem[10]) + transformElem[14];
|
||
result.w = (vectorX * transformElem[3]) + (vectorY * transformElem[7]) + (vectorZ * transformElem[11]) + transformElem[15];
|
||
}
|
||
static TransformNormal(normal, transform, result) {
|
||
var normalX = normal.x;
|
||
var normalY = normal.y;
|
||
var normalZ = normal.z;
|
||
var transformElem = transform.elements;
|
||
result.x = (normalX * transformElem[0]) + (normalY * transformElem[4]) + (normalZ * transformElem[8]);
|
||
result.y = (normalX * transformElem[1]) + (normalY * transformElem[5]) + (normalZ * transformElem[9]);
|
||
result.z = (normalX * transformElem[2]) + (normalY * transformElem[6]) + (normalZ * transformElem[10]);
|
||
}
|
||
static transformCoordinate(coordinate, transform, result) {
|
||
var coordinateX = coordinate.x;
|
||
var coordinateY = coordinate.y;
|
||
var coordinateZ = coordinate.z;
|
||
var transformElem = transform.elements;
|
||
var w = coordinateX * transformElem[3] + coordinateY * transformElem[7] + coordinateZ * transformElem[11] + transformElem[15];
|
||
result.x = (coordinateX * transformElem[0] + coordinateY * transformElem[4] + coordinateZ * transformElem[8] + transformElem[12]) / w;
|
||
result.y = (coordinateX * transformElem[1] + coordinateY * transformElem[5] + coordinateZ * transformElem[9] + transformElem[13]) / w;
|
||
result.z = (coordinateX * transformElem[2] + coordinateY * transformElem[6] + coordinateZ * transformElem[10] + transformElem[14]) / w;
|
||
}
|
||
static Clamp(value, min, max, out) {
|
||
var x = value.x;
|
||
var y = value.y;
|
||
var z = value.z;
|
||
var mineX = min.x;
|
||
var mineY = min.y;
|
||
var mineZ = min.z;
|
||
var maxeX = max.x;
|
||
var maxeY = max.y;
|
||
var maxeZ = max.z;
|
||
x = (x > maxeX) ? maxeX : x;
|
||
x = (x < mineX) ? mineX : x;
|
||
y = (y > maxeY) ? maxeY : y;
|
||
y = (y < mineY) ? mineY : y;
|
||
z = (z > maxeZ) ? maxeZ : z;
|
||
z = (z < mineZ) ? mineZ : z;
|
||
out.x = x;
|
||
out.y = y;
|
||
out.z = z;
|
||
}
|
||
static add(a, b, out) {
|
||
out.x = a.x + b.x;
|
||
out.y = a.y + b.y;
|
||
out.z = a.z + b.z;
|
||
}
|
||
static subtract(a, b, o) {
|
||
o.x = a.x - b.x;
|
||
o.y = a.y - b.y;
|
||
o.z = a.z - b.z;
|
||
}
|
||
static cross(a, b, o) {
|
||
var ax = a.x, ay = a.y, az = a.z, bx = b.x, by = b.y, bz = b.z;
|
||
o.x = ay * bz - az * by;
|
||
o.y = az * bx - ax * bz;
|
||
o.z = ax * by - ay * bx;
|
||
}
|
||
static dot(a, b) {
|
||
return (a.x * b.x) + (a.y * b.y) + (a.z * b.z);
|
||
}
|
||
static equals(a, b) {
|
||
return MathUtils3D.nearEqual(a.x, b.x) && MathUtils3D.nearEqual(a.y, b.y) && MathUtils3D.nearEqual(a.z, b.z);
|
||
}
|
||
setValue(x, y, z) {
|
||
this.x = x;
|
||
this.y = y;
|
||
this.z = z;
|
||
}
|
||
fromArray(array, offset = 0) {
|
||
this.x = array[offset + 0];
|
||
this.y = array[offset + 1];
|
||
this.z = array[offset + 2];
|
||
}
|
||
toArray(array, offset = 0) {
|
||
array[offset + 0] = this.x;
|
||
array[offset + 1] = this.y;
|
||
array[offset + 2] = this.z;
|
||
}
|
||
cloneTo(destObject) {
|
||
var destVector3 = destObject;
|
||
destVector3.x = this.x;
|
||
destVector3.y = this.y;
|
||
destVector3.z = this.z;
|
||
}
|
||
clone() {
|
||
var destVector3 = new Vector3();
|
||
this.cloneTo(destVector3);
|
||
return destVector3;
|
||
}
|
||
toDefault() {
|
||
this.x = 0;
|
||
this.y = 0;
|
||
this.z = 0;
|
||
}
|
||
forNativeElement(nativeElements = null) {
|
||
if (nativeElements) {
|
||
this.elements = nativeElements;
|
||
this.elements[0] = this.x;
|
||
this.elements[1] = this.y;
|
||
this.elements[2] = this.z;
|
||
}
|
||
else {
|
||
this.elements = new Float32Array([this.x, this.y, this.z]);
|
||
}
|
||
Vector2.rewriteNumProperty(this, "x", 0);
|
||
Vector2.rewriteNumProperty(this, "y", 1);
|
||
Vector2.rewriteNumProperty(this, "z", 2);
|
||
}
|
||
}
|
||
Vector3._tempVector4 = new Vector4();
|
||
Vector3._ZERO = new Vector3(0.0, 0.0, 0.0);
|
||
Vector3._ONE = new Vector3(1.0, 1.0, 1.0);
|
||
Vector3._NegativeUnitX = new Vector3(-1, 0, 0);
|
||
Vector3._UnitX = new Vector3(1, 0, 0);
|
||
Vector3._UnitY = new Vector3(0, 1, 0);
|
||
Vector3._UnitZ = new Vector3(0, 0, 1);
|
||
Vector3._ForwardRH = new Vector3(0, 0, -1);
|
||
Vector3._ForwardLH = new Vector3(0, 0, 1);
|
||
Vector3._Up = new Vector3(0, 1, 0);
|
||
|
||
(function (PBRRenderQuality) {
|
||
PBRRenderQuality[PBRRenderQuality["High"] = 0] = "High";
|
||
PBRRenderQuality[PBRRenderQuality["Low"] = 1] = "Low";
|
||
})(exports.PBRRenderQuality || (exports.PBRRenderQuality = {}));
|
||
|
||
class ILaya3D {
|
||
}
|
||
ILaya3D.Shader3D = null;
|
||
ILaya3D.Scene3D = null;
|
||
ILaya3D.MeshRenderStaticBatchManager = null;
|
||
ILaya3D.MeshRenderDynamicBatchManager = null;
|
||
ILaya3D.SubMeshDynamicBatch = null;
|
||
ILaya3D.Laya3D = null;
|
||
ILaya3D.Matrix4x4 = null;
|
||
ILaya3D.Physics3D = null;
|
||
ILaya3D.ShadowLightType = null;
|
||
ILaya3D.RenderElement = null;
|
||
ILaya3D.CommandBuffer = null;
|
||
ILaya3D.Camera = null;
|
||
ILaya3D.SubMeshRenderElement = null;
|
||
|
||
class Physics3D {
|
||
static __bulletinit__() {
|
||
this._bullet = window.Physics3D;
|
||
if (this._bullet) {
|
||
Laya.StaticPlaneColliderShape.__init__();
|
||
Laya.ColliderShape.__init__();
|
||
Laya.CompoundColliderShape.__init__();
|
||
Laya.PhysicsComponent.__init__();
|
||
Laya.PhysicsSimulation.__init__();
|
||
Laya.BoxColliderShape.__init__();
|
||
Laya.CylinderColliderShape.__init__();
|
||
Laya.CharacterController.__init__();
|
||
Laya.Rigidbody3D.__init__();
|
||
}
|
||
}
|
||
static __cannoninit__() {
|
||
this._cannon = window.CANNON;
|
||
if (!this._cannon)
|
||
return;
|
||
Laya.CannonColliderShape.__init__();
|
||
Laya.CannonPhysicsComponent.__init__();
|
||
Laya.CannonPhysicsSimulation.__init__();
|
||
Laya.CannonBoxColliderShape.__init__();
|
||
Laya.CannonRigidbody3D.__init__();
|
||
}
|
||
}
|
||
Physics3D._bullet = null;
|
||
Physics3D._cannon = null;
|
||
Physics3D._enablePhysics = false;
|
||
|
||
class Config3D {
|
||
constructor() {
|
||
this._defaultPhysicsMemory = 16;
|
||
this._maxLightCount = 32;
|
||
this._lightClusterCount = new Vector3(12, 12, 12);
|
||
this._editerEnvironment = false;
|
||
this.isAntialias = true;
|
||
this.isAlpha = false;
|
||
this.premultipliedAlpha = true;
|
||
this.isStencil = true;
|
||
this.enableMultiLight = true;
|
||
this.octreeCulling = false;
|
||
this.octreeInitialSize = 64.0;
|
||
this.octreeInitialCenter = new Vector3(0, 0, 0);
|
||
this.octreeMinNodeSize = 2.0;
|
||
this.octreeLooseness = 1.25;
|
||
this.debugFrustumCulling = false;
|
||
this.pbrRenderQuality = exports.PBRRenderQuality.High;
|
||
this.isUseCannonPhysicsEngine = false;
|
||
this._maxAreaLightCountPerClusterAverage = Math.min(Math.floor(2048 / this._lightClusterCount.z - 1) * 4, this._maxLightCount);
|
||
}
|
||
static get useCannonPhysics() {
|
||
return Config3D._config.isUseCannonPhysicsEngine;
|
||
}
|
||
static set useCannonPhysics(value) {
|
||
Config3D._config.isUseCannonPhysicsEngine = value;
|
||
if (value) {
|
||
Physics3D.__cannoninit__();
|
||
if (!ILaya3D.Scene3D.cannonPhysicsSettings)
|
||
ILaya3D.Scene3D.cannonPhysicsSettings = new Laya.CannonPhysicsSettings();
|
||
}
|
||
}
|
||
static set enableDynamicManager(value) {
|
||
ILaya3D.SubMeshRenderElement.enableDynamicBatch = value;
|
||
}
|
||
static get enableDynamicManager() {
|
||
return ILaya3D.SubMeshRenderElement.enableDynamicBatch;
|
||
}
|
||
static set enableStaticManager(value) {
|
||
ILaya3D.SubMeshRenderElement.enableStaticBatch = value;
|
||
}
|
||
static get enableStaticManager() {
|
||
return ILaya3D.SubMeshRenderElement.enableStaticBatch;
|
||
}
|
||
get defaultPhysicsMemory() {
|
||
return this._defaultPhysicsMemory;
|
||
}
|
||
set defaultPhysicsMemory(value) {
|
||
if (value < 16)
|
||
throw "defaultPhysicsMemory must large than 16M";
|
||
this._defaultPhysicsMemory = value;
|
||
}
|
||
get maxLightCount() {
|
||
return this._maxLightCount;
|
||
}
|
||
set maxLightCount(value) {
|
||
if (value > 2048) {
|
||
this._maxLightCount = 2048;
|
||
console.warn("Config3D: maxLightCount must less equal 2048.");
|
||
}
|
||
else {
|
||
this._maxLightCount = value;
|
||
}
|
||
}
|
||
get lightClusterCount() {
|
||
return this._lightClusterCount;
|
||
}
|
||
set lightClusterCount(value) {
|
||
if (value.x > 128 || value.y > 128 || value.z > 128) {
|
||
this._lightClusterCount.setValue(Math.min(value.x, 128), Math.min(value.y, 128), Math.min(value.z, 128));
|
||
console.warn("Config3D: lightClusterCount X and Y、Z must less equal 128.");
|
||
}
|
||
else {
|
||
value.cloneTo(this._lightClusterCount);
|
||
}
|
||
var maxAreaLightCountWithZ = Math.floor(2048 / this._lightClusterCount.z - 1) * 4;
|
||
if (maxAreaLightCountWithZ < this._maxLightCount)
|
||
console.warn("Config3D: if the area light(PointLight、SpotLight) count is large than " + maxAreaLightCountWithZ + ",maybe the far away culster will ingonre some light.");
|
||
this._maxAreaLightCountPerClusterAverage = Math.min(maxAreaLightCountWithZ, this._maxLightCount);
|
||
}
|
||
cloneTo(dest) {
|
||
var destConfig3D = dest;
|
||
destConfig3D._defaultPhysicsMemory = this._defaultPhysicsMemory;
|
||
destConfig3D._editerEnvironment = this._editerEnvironment;
|
||
destConfig3D.isAntialias = this.isAntialias;
|
||
destConfig3D.isAlpha = this.isAlpha;
|
||
destConfig3D.premultipliedAlpha = this.premultipliedAlpha;
|
||
destConfig3D.isStencil = this.isStencil;
|
||
destConfig3D.octreeCulling = this.octreeCulling;
|
||
this.octreeInitialCenter.cloneTo(destConfig3D.octreeInitialCenter);
|
||
destConfig3D.octreeInitialSize = this.octreeInitialSize;
|
||
destConfig3D.octreeMinNodeSize = this.octreeMinNodeSize;
|
||
destConfig3D.octreeLooseness = this.octreeLooseness;
|
||
destConfig3D.debugFrustumCulling = this.debugFrustumCulling;
|
||
destConfig3D.maxLightCount = this.maxLightCount;
|
||
destConfig3D.enableMultiLight = this.enableMultiLight;
|
||
var lightClusterCount = destConfig3D.lightClusterCount;
|
||
this.lightClusterCount.cloneTo(lightClusterCount);
|
||
destConfig3D.lightClusterCount = lightClusterCount;
|
||
destConfig3D.pbrRenderQuality = this.pbrRenderQuality;
|
||
}
|
||
clone() {
|
||
var dest = new Config3D();
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
}
|
||
Config3D._config = new Config3D();
|
||
window.Config3D = Config3D;
|
||
|
||
class KeyframeNode {
|
||
constructor() {
|
||
this._ownerPath = [];
|
||
this._propertys = [];
|
||
this._keyFrames = [];
|
||
}
|
||
get ownerPathCount() {
|
||
return this._ownerPath.length;
|
||
}
|
||
get propertyCount() {
|
||
return this._propertys.length;
|
||
}
|
||
get keyFramesCount() {
|
||
return this._keyFrames.length;
|
||
}
|
||
_setOwnerPathCount(value) {
|
||
this._ownerPath.length = value;
|
||
}
|
||
_setOwnerPathByIndex(index, value) {
|
||
this._ownerPath[index] = value;
|
||
}
|
||
_joinOwnerPath(sep) {
|
||
return this._ownerPath.join(sep);
|
||
}
|
||
_setPropertyCount(value) {
|
||
this._propertys.length = value;
|
||
}
|
||
_setPropertyByIndex(index, value) {
|
||
this._propertys[index] = value;
|
||
}
|
||
_joinProperty(sep) {
|
||
return this._propertys.join(sep);
|
||
}
|
||
_setKeyframeCount(value) {
|
||
this._keyFrames.length = value;
|
||
}
|
||
_setKeyframeByIndex(index, value) {
|
||
this._keyFrames[index] = value;
|
||
}
|
||
getOwnerPathByIndex(index) {
|
||
return this._ownerPath[index];
|
||
}
|
||
getPropertyByIndex(index) {
|
||
return this._propertys[index];
|
||
}
|
||
getKeyframeByIndex(index) {
|
||
return this._keyFrames[index];
|
||
}
|
||
}
|
||
|
||
class AnimationEvent {
|
||
constructor() {
|
||
}
|
||
}
|
||
|
||
class Keyframe {
|
||
constructor() {
|
||
}
|
||
cloneTo(destObject) {
|
||
var destKeyFrame = destObject;
|
||
destKeyFrame.time = this.time;
|
||
}
|
||
clone() {
|
||
var dest = new Keyframe();
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
}
|
||
|
||
class FloatKeyframe extends Keyframe {
|
||
constructor() {
|
||
super();
|
||
}
|
||
cloneTo(destObject) {
|
||
super.cloneTo(destObject);
|
||
var destKeyFrame = destObject;
|
||
destKeyFrame.inTangent = this.inTangent;
|
||
destKeyFrame.outTangent = this.outTangent;
|
||
destKeyFrame.value = this.value;
|
||
}
|
||
}
|
||
|
||
class Matrix3x3 {
|
||
constructor() {
|
||
var e = this.elements = new Float32Array(9);
|
||
e[0] = 1;
|
||
e[1] = 0;
|
||
e[2] = 0;
|
||
e[3] = 0;
|
||
e[4] = 1;
|
||
e[5] = 0;
|
||
e[6] = 0;
|
||
e[7] = 0;
|
||
e[8] = 1;
|
||
}
|
||
static createRotationQuaternion(rotation, out) {
|
||
var rotX = rotation.x;
|
||
var rotY = rotation.y;
|
||
var rotZ = rotation.z;
|
||
var rotW = rotation.w;
|
||
var xx = rotX * rotX;
|
||
var yy = rotY * rotY;
|
||
var zz = rotZ * rotZ;
|
||
var xy = rotX * rotY;
|
||
var zw = rotZ * rotW;
|
||
var zx = rotZ * rotX;
|
||
var yw = rotY * rotW;
|
||
var yz = rotY * rotZ;
|
||
var xw = rotX * rotW;
|
||
var resultE = out.elements;
|
||
resultE[0] = 1.0 - (2.0 * (yy + zz));
|
||
resultE[1] = 2.0 * (xy + zw);
|
||
resultE[2] = 2.0 * (zx - yw);
|
||
resultE[3] = 2.0 * (xy - zw);
|
||
resultE[4] = 1.0 - (2.0 * (zz + xx));
|
||
resultE[5] = 2.0 * (yz + xw);
|
||
resultE[6] = 2.0 * (zx + yw);
|
||
resultE[7] = 2.0 * (yz - xw);
|
||
resultE[8] = 1.0 - (2.0 * (yy + xx));
|
||
}
|
||
static createFromTranslation(trans, out) {
|
||
var e = out.elements;
|
||
e[0] = 1;
|
||
e[1] = 0;
|
||
e[2] = 0;
|
||
e[3] = 0;
|
||
e[4] = 1;
|
||
e[5] = 0;
|
||
e[6] = trans.x;
|
||
e[7] = trans.y;
|
||
e[8] = 1;
|
||
}
|
||
static createFromRotation(rad, out) {
|
||
var e = out.elements;
|
||
var s = Math.sin(rad), c = Math.cos(rad);
|
||
e[0] = c;
|
||
e[1] = s;
|
||
e[2] = 0;
|
||
e[3] = -s;
|
||
e[4] = c;
|
||
e[5] = 0;
|
||
e[6] = 0;
|
||
e[7] = 0;
|
||
e[8] = 1;
|
||
}
|
||
static createFromScaling(scale, out) {
|
||
var e = out.elements;
|
||
e[0] = scale.x;
|
||
e[1] = 0;
|
||
e[2] = 0;
|
||
e[3] = 0;
|
||
e[4] = scale.y;
|
||
e[5] = 0;
|
||
e[6] = 0;
|
||
e[7] = 0;
|
||
e[8] = scale.z;
|
||
}
|
||
static createFromMatrix4x4(sou, out) {
|
||
var souE = sou.elements;
|
||
var outE = out.elements;
|
||
outE[0] = souE[0];
|
||
outE[1] = souE[1];
|
||
outE[2] = souE[2];
|
||
outE[3] = souE[4];
|
||
outE[4] = souE[5];
|
||
outE[5] = souE[6];
|
||
outE[6] = souE[8];
|
||
outE[7] = souE[9];
|
||
outE[8] = souE[10];
|
||
}
|
||
static multiply(left, right, out) {
|
||
var l = left.elements;
|
||
var r = right.elements;
|
||
var e = out.elements;
|
||
var l11 = l[0], l12 = l[1], l13 = l[2];
|
||
var l21 = l[3], l22 = l[4], l23 = l[5];
|
||
var l31 = l[6], l32 = l[7], l33 = l[8];
|
||
var r11 = r[0], r12 = r[1], r13 = r[2];
|
||
var r21 = r[3], r22 = r[4], r23 = r[5];
|
||
var r31 = r[6], r32 = r[7], r33 = r[8];
|
||
e[0] = r11 * l11 + r12 * l21 + r13 * l31;
|
||
e[1] = r11 * l12 + r12 * l22 + r13 * r32;
|
||
e[2] = r11 * l13 + r12 * l23 + r13 * l33;
|
||
e[3] = r21 * l11 + r22 * l21 + r23 * l31;
|
||
e[4] = r21 * l12 + r22 * l22 + r23 * l32;
|
||
e[5] = r21 * l13 + r22 * l23 + r23 * l33;
|
||
e[6] = r31 * l11 + r32 * l21 + r33 * l31;
|
||
e[7] = r31 * l12 + r32 * l22 + r33 * l32;
|
||
e[8] = r31 * l13 + r32 * l23 + r33 * l33;
|
||
}
|
||
determinant() {
|
||
var f = this.elements;
|
||
var a00 = f[0], a01 = f[1], a02 = f[2];
|
||
var a10 = f[3], a11 = f[4], a12 = f[5];
|
||
var a20 = f[6], a21 = f[7], a22 = f[8];
|
||
return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20);
|
||
}
|
||
translate(trans, out) {
|
||
var e = out.elements;
|
||
var f = this.elements;
|
||
var a00 = f[0], a01 = f[1], a02 = f[2];
|
||
var a10 = f[3], a11 = f[4], a12 = f[5];
|
||
var a20 = f[6], a21 = f[7], a22 = f[8];
|
||
var x = trans.x, y = trans.y;
|
||
e[0] = a00;
|
||
e[1] = a01;
|
||
e[2] = a02;
|
||
e[3] = a10;
|
||
e[4] = a11;
|
||
e[5] = a12;
|
||
e[6] = x * a00 + y * a10 + a20;
|
||
e[7] = x * a01 + y * a11 + a21;
|
||
e[8] = x * a02 + y * a12 + a22;
|
||
}
|
||
rotate(rad, out) {
|
||
var e = out.elements;
|
||
var f = this.elements;
|
||
var a00 = f[0], a01 = f[1], a02 = f[2];
|
||
var a10 = f[3], a11 = f[4], a12 = f[5];
|
||
var a20 = f[6], a21 = f[7], a22 = f[8];
|
||
var s = Math.sin(rad);
|
||
var c = Math.cos(rad);
|
||
e[0] = c * a00 + s * a10;
|
||
e[1] = c * a01 + s * a11;
|
||
e[2] = c * a02 + s * a12;
|
||
e[3] = c * a10 - s * a00;
|
||
e[4] = c * a11 - s * a01;
|
||
e[5] = c * a12 - s * a02;
|
||
e[6] = a20;
|
||
e[7] = a21;
|
||
e[8] = a22;
|
||
}
|
||
scale(scale, out) {
|
||
var e = out.elements;
|
||
var f = this.elements;
|
||
var x = scale.x, y = scale.y;
|
||
e[0] = x * f[0];
|
||
e[1] = x * f[1];
|
||
e[2] = x * f[2];
|
||
e[3] = y * f[3];
|
||
e[4] = y * f[4];
|
||
e[5] = y * f[5];
|
||
e[6] = f[6];
|
||
e[7] = f[7];
|
||
e[8] = f[8];
|
||
}
|
||
invert(out) {
|
||
var e = out.elements;
|
||
var f = this.elements;
|
||
var a00 = f[0], a01 = f[1], a02 = f[2];
|
||
var a10 = f[3], a11 = f[4], a12 = f[5];
|
||
var a20 = f[6], a21 = f[7], a22 = f[8];
|
||
var b01 = a22 * a11 - a12 * a21;
|
||
var b11 = -a22 * a10 + a12 * a20;
|
||
var b21 = a21 * a10 - a11 * a20;
|
||
var det = a00 * b01 + a01 * b11 + a02 * b21;
|
||
if (!det) {
|
||
return;
|
||
}
|
||
det = 1.0 / det;
|
||
e[0] = b01 * det;
|
||
e[1] = (-a22 * a01 + a02 * a21) * det;
|
||
e[2] = (a12 * a01 - a02 * a11) * det;
|
||
e[3] = b11 * det;
|
||
e[4] = (a22 * a00 - a02 * a20) * det;
|
||
e[5] = (-a12 * a00 + a02 * a10) * det;
|
||
e[6] = b21 * det;
|
||
e[7] = (-a21 * a00 + a01 * a20) * det;
|
||
e[8] = (a11 * a00 - a01 * a10) * det;
|
||
}
|
||
transpose(out) {
|
||
var e = out.elements;
|
||
var f = this.elements;
|
||
if (out === this) {
|
||
var a01 = f[1], a02 = f[2], a12 = f[5];
|
||
e[1] = f[3];
|
||
e[2] = f[6];
|
||
e[3] = a01;
|
||
e[5] = f[7];
|
||
e[6] = a02;
|
||
e[7] = a12;
|
||
}
|
||
else {
|
||
e[0] = f[0];
|
||
e[1] = f[3];
|
||
e[2] = f[6];
|
||
e[3] = f[1];
|
||
e[4] = f[4];
|
||
e[5] = f[7];
|
||
e[6] = f[2];
|
||
e[7] = f[5];
|
||
e[8] = f[8];
|
||
}
|
||
}
|
||
identity() {
|
||
var e = this.elements;
|
||
e[0] = 1;
|
||
e[1] = 0;
|
||
e[2] = 0;
|
||
e[3] = 0;
|
||
e[4] = 1;
|
||
e[5] = 0;
|
||
e[6] = 0;
|
||
e[7] = 0;
|
||
e[8] = 1;
|
||
}
|
||
cloneTo(destObject) {
|
||
var i, s, d;
|
||
s = this.elements;
|
||
d = destObject.elements;
|
||
if (s === d) {
|
||
return;
|
||
}
|
||
for (i = 0; i < 9; ++i) {
|
||
d[i] = s[i];
|
||
}
|
||
}
|
||
clone() {
|
||
var dest = new Matrix3x3();
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
static lookAt(eye, target, up, out) {
|
||
Vector3.subtract(eye, target, Matrix3x3._tempV30);
|
||
Vector3.normalize(Matrix3x3._tempV30, Matrix3x3._tempV30);
|
||
Vector3.cross(up, Matrix3x3._tempV30, Matrix3x3._tempV31);
|
||
Vector3.normalize(Matrix3x3._tempV31, Matrix3x3._tempV31);
|
||
Vector3.cross(Matrix3x3._tempV30, Matrix3x3._tempV31, Matrix3x3._tempV32);
|
||
var v0 = Matrix3x3._tempV30;
|
||
var v1 = Matrix3x3._tempV31;
|
||
var v2 = Matrix3x3._tempV32;
|
||
var me = out.elements;
|
||
me[0] = v1.x;
|
||
me[3] = v1.y;
|
||
me[6] = v1.z;
|
||
me[1] = v2.x;
|
||
me[4] = v2.y;
|
||
me[7] = v2.z;
|
||
me[2] = v0.x;
|
||
me[5] = v0.y;
|
||
me[8] = v0.z;
|
||
}
|
||
}
|
||
Matrix3x3.DEFAULT = new Matrix3x3();
|
||
Matrix3x3._tempV30 = new Vector3();
|
||
Matrix3x3._tempV31 = new Vector3();
|
||
Matrix3x3._tempV32 = new Vector3();
|
||
|
||
class Quaternion {
|
||
constructor(x = 0, y = 0, z = 0, w = 1) {
|
||
this.x = x;
|
||
this.y = y;
|
||
this.z = z;
|
||
this.w = w;
|
||
}
|
||
static createFromYawPitchRoll(yaw, pitch, roll, out) {
|
||
var halfRoll = roll * 0.5;
|
||
var halfPitch = pitch * 0.5;
|
||
var halfYaw = yaw * 0.5;
|
||
var sinRoll = Math.sin(halfRoll);
|
||
var cosRoll = Math.cos(halfRoll);
|
||
var sinPitch = Math.sin(halfPitch);
|
||
var cosPitch = Math.cos(halfPitch);
|
||
var sinYaw = Math.sin(halfYaw);
|
||
var cosYaw = Math.cos(halfYaw);
|
||
out.x = (cosYaw * sinPitch * cosRoll) + (sinYaw * cosPitch * sinRoll);
|
||
out.y = (sinYaw * cosPitch * cosRoll) - (cosYaw * sinPitch * sinRoll);
|
||
out.z = (cosYaw * cosPitch * sinRoll) - (sinYaw * sinPitch * cosRoll);
|
||
out.w = (cosYaw * cosPitch * cosRoll) + (sinYaw * sinPitch * sinRoll);
|
||
}
|
||
static multiply(left, right, out) {
|
||
var lx = left.x;
|
||
var ly = left.y;
|
||
var lz = left.z;
|
||
var lw = left.w;
|
||
var rx = right.x;
|
||
var ry = right.y;
|
||
var rz = right.z;
|
||
var rw = right.w;
|
||
var a = (ly * rz - lz * ry);
|
||
var b = (lz * rx - lx * rz);
|
||
var c = (lx * ry - ly * rx);
|
||
var d = (lx * rx + ly * ry + lz * rz);
|
||
out.x = (lx * rw + rx * lw) + a;
|
||
out.y = (ly * rw + ry * lw) + b;
|
||
out.z = (lz * rw + rz * lw) + c;
|
||
out.w = lw * rw - d;
|
||
}
|
||
static arcTanAngle(x, y) {
|
||
if (x == 0) {
|
||
if (y == 1)
|
||
return Math.PI / 2;
|
||
return -Math.PI / 2;
|
||
}
|
||
if (x > 0)
|
||
return Math.atan(y / x);
|
||
if (x < 0) {
|
||
if (y > 0)
|
||
return Math.atan(y / x) + Math.PI;
|
||
return Math.atan(y / x) - Math.PI;
|
||
}
|
||
return 0;
|
||
}
|
||
static angleTo(from, location, angle) {
|
||
Vector3.subtract(location, from, Quaternion.TEMPVector30);
|
||
Vector3.normalize(Quaternion.TEMPVector30, Quaternion.TEMPVector30);
|
||
angle.x = Math.asin(Quaternion.TEMPVector30.y);
|
||
angle.y = Quaternion.arcTanAngle(-Quaternion.TEMPVector30.z, -Quaternion.TEMPVector30.x);
|
||
}
|
||
static createFromAxisAngle(axis, rad, out) {
|
||
rad = rad * 0.5;
|
||
var s = Math.sin(rad);
|
||
out.x = s * axis.x;
|
||
out.y = s * axis.y;
|
||
out.z = s * axis.z;
|
||
out.w = Math.cos(rad);
|
||
}
|
||
static createFromMatrix4x4(mat, out) {
|
||
var me = mat.elements;
|
||
var sqrt;
|
||
var half;
|
||
var scale = me[0] + me[5] + me[10];
|
||
if (scale > 0.0) {
|
||
sqrt = Math.sqrt(scale + 1.0);
|
||
out.w = sqrt * 0.5;
|
||
sqrt = 0.5 / sqrt;
|
||
out.x = (me[6] - me[9]) * sqrt;
|
||
out.y = (me[8] - me[2]) * sqrt;
|
||
out.z = (me[1] - me[4]) * sqrt;
|
||
}
|
||
else if ((me[0] >= me[5]) && (me[0] >= me[10])) {
|
||
sqrt = Math.sqrt(1.0 + me[0] - me[5] - me[10]);
|
||
half = 0.5 / sqrt;
|
||
out.x = 0.5 * sqrt;
|
||
out.y = (me[1] + me[4]) * half;
|
||
out.z = (me[2] + me[8]) * half;
|
||
out.w = (me[6] - me[9]) * half;
|
||
}
|
||
else if (me[5] > me[10]) {
|
||
sqrt = Math.sqrt(1.0 + me[5] - me[0] - me[10]);
|
||
half = 0.5 / sqrt;
|
||
out.x = (me[4] + me[1]) * half;
|
||
out.y = 0.5 * sqrt;
|
||
out.z = (me[9] + me[6]) * half;
|
||
out.w = (me[8] - me[2]) * half;
|
||
}
|
||
else {
|
||
sqrt = Math.sqrt(1.0 + me[10] - me[0] - me[5]);
|
||
half = 0.5 / sqrt;
|
||
out.x = (me[8] + me[2]) * half;
|
||
out.y = (me[9] + me[6]) * half;
|
||
out.z = 0.5 * sqrt;
|
||
out.w = (me[1] - me[4]) * half;
|
||
}
|
||
}
|
||
static slerp(left, right, t, out) {
|
||
var ax = left.x, ay = left.y, az = left.z, aw = left.w, bx = right.x, by = right.y, bz = right.z, bw = right.w;
|
||
var omega, cosom, sinom, scale0, scale1;
|
||
cosom = ax * bx + ay * by + az * bz + aw * bw;
|
||
if (cosom < 0.0) {
|
||
cosom = -cosom;
|
||
bx = -bx;
|
||
by = -by;
|
||
bz = -bz;
|
||
bw = -bw;
|
||
}
|
||
if ((1.0 - cosom) > 0.000001) {
|
||
omega = Math.acos(cosom);
|
||
sinom = Math.sin(omega);
|
||
scale0 = Math.sin((1.0 - t) * omega) / sinom;
|
||
scale1 = Math.sin(t * omega) / sinom;
|
||
}
|
||
else {
|
||
scale0 = 1.0 - t;
|
||
scale1 = t;
|
||
}
|
||
out.x = scale0 * ax + scale1 * bx;
|
||
out.y = scale0 * ay + scale1 * by;
|
||
out.z = scale0 * az + scale1 * bz;
|
||
out.w = scale0 * aw + scale1 * bw;
|
||
return out;
|
||
}
|
||
static lerp(left, right, amount, out) {
|
||
var inverse = 1.0 - amount;
|
||
if (Quaternion.dot(left, right) >= 0) {
|
||
out.x = (inverse * left.x) + (amount * right.x);
|
||
out.y = (inverse * left.y) + (amount * right.y);
|
||
out.z = (inverse * left.z) + (amount * right.z);
|
||
out.w = (inverse * left.w) + (amount * right.w);
|
||
}
|
||
else {
|
||
out.x = (inverse * left.x) - (amount * right.x);
|
||
out.y = (inverse * left.y) - (amount * right.y);
|
||
out.z = (inverse * left.z) - (amount * right.z);
|
||
out.w = (inverse * left.w) - (amount * right.w);
|
||
}
|
||
out.normalize(out);
|
||
}
|
||
static add(left, right, out) {
|
||
out.x = left.x + right.x;
|
||
out.y = left.y + right.y;
|
||
out.z = left.z + right.z;
|
||
out.w = left.w + right.w;
|
||
}
|
||
static dot(left, right) {
|
||
return left.x * right.x + left.y * right.y + left.z * right.z + left.w * right.w;
|
||
}
|
||
scaling(scaling, out) {
|
||
out.x = this.x * scaling;
|
||
out.y = this.y * scaling;
|
||
out.z = this.z * scaling;
|
||
out.w = this.w * scaling;
|
||
}
|
||
normalize(out) {
|
||
var len = this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
|
||
if (len > 0) {
|
||
len = 1 / Math.sqrt(len);
|
||
out.x = this.x * len;
|
||
out.y = this.y * len;
|
||
out.z = this.z * len;
|
||
out.w = this.w * len;
|
||
}
|
||
}
|
||
length() {
|
||
return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);
|
||
}
|
||
rotateX(rad, out) {
|
||
rad *= 0.5;
|
||
var bx = Math.sin(rad), bw = Math.cos(rad);
|
||
out.x = this.x * bw + this.w * bx;
|
||
out.y = this.y * bw + this.z * bx;
|
||
out.z = this.z * bw - this.y * bx;
|
||
out.w = this.w * bw - this.x * bx;
|
||
}
|
||
rotateY(rad, out) {
|
||
rad *= 0.5;
|
||
var by = Math.sin(rad), bw = Math.cos(rad);
|
||
out.x = this.x * bw - this.z * by;
|
||
out.y = this.y * bw + this.w * by;
|
||
out.z = this.z * bw + this.x * by;
|
||
out.w = this.w * bw - this.y * by;
|
||
}
|
||
rotateZ(rad, out) {
|
||
rad *= 0.5;
|
||
var bz = Math.sin(rad), bw = Math.cos(rad);
|
||
out.x = this.x * bw + this.y * bz;
|
||
out.y = this.y * bw - this.x * bz;
|
||
out.z = this.z * bw + this.w * bz;
|
||
out.w = this.w * bw - this.z * bz;
|
||
}
|
||
getYawPitchRoll(out) {
|
||
Vector3.transformQuat(Vector3._ForwardRH, this, Quaternion.TEMPVector31);
|
||
Vector3.transformQuat(Vector3._Up, this, Quaternion.TEMPVector32);
|
||
var upe = Quaternion.TEMPVector32;
|
||
Quaternion.angleTo(Vector3._ZERO, Quaternion.TEMPVector31, Quaternion.TEMPVector33);
|
||
var angle = Quaternion.TEMPVector33;
|
||
if (angle.x == Math.PI / 2) {
|
||
angle.y = Quaternion.arcTanAngle(upe.z, upe.x);
|
||
angle.z = 0;
|
||
}
|
||
else if (angle.x == -Math.PI / 2) {
|
||
angle.y = Quaternion.arcTanAngle(-upe.z, -upe.x);
|
||
angle.z = 0;
|
||
}
|
||
else {
|
||
ILaya3D.Matrix4x4.createRotationY(-angle.y, ILaya3D.Matrix4x4.TEMPMatrix0);
|
||
ILaya3D.Matrix4x4.createRotationX(-angle.x, ILaya3D.Matrix4x4.TEMPMatrix1);
|
||
Vector3.transformCoordinate(Quaternion.TEMPVector32, ILaya3D.Matrix4x4.TEMPMatrix0, Quaternion.TEMPVector32);
|
||
Vector3.transformCoordinate(Quaternion.TEMPVector32, ILaya3D.Matrix4x4.TEMPMatrix1, Quaternion.TEMPVector32);
|
||
angle.z = Quaternion.arcTanAngle(upe.y, -upe.x);
|
||
}
|
||
if (angle.y <= -Math.PI)
|
||
angle.y = Math.PI;
|
||
if (angle.z <= -Math.PI)
|
||
angle.z = Math.PI;
|
||
if (angle.y >= Math.PI && angle.z >= Math.PI) {
|
||
angle.y = 0;
|
||
angle.z = 0;
|
||
angle.x = Math.PI - angle.x;
|
||
}
|
||
var oe = out;
|
||
oe.x = angle.y;
|
||
oe.y = angle.x;
|
||
oe.z = angle.z;
|
||
}
|
||
invert(out) {
|
||
var a0 = this.x, a1 = this.y, a2 = this.z, a3 = this.w;
|
||
var dot = a0 * a0 + a1 * a1 + a2 * a2 + a3 * a3;
|
||
var invDot = dot ? 1.0 / dot : 0;
|
||
out.x = -a0 * invDot;
|
||
out.y = -a1 * invDot;
|
||
out.z = -a2 * invDot;
|
||
out.w = a3 * invDot;
|
||
}
|
||
identity() {
|
||
this.x = 0;
|
||
this.y = 0;
|
||
this.z = 0;
|
||
this.w = 1;
|
||
}
|
||
fromArray(array, offset = 0) {
|
||
this.x = array[offset + 0];
|
||
this.y = array[offset + 1];
|
||
this.z = array[offset + 2];
|
||
this.w = array[offset + 3];
|
||
}
|
||
cloneTo(destObject) {
|
||
if (this === destObject) {
|
||
return;
|
||
}
|
||
destObject.x = this.x;
|
||
destObject.y = this.y;
|
||
destObject.z = this.z;
|
||
destObject.w = this.w;
|
||
}
|
||
clone() {
|
||
var dest = new Quaternion();
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
equals(b) {
|
||
return MathUtils3D.nearEqual(this.x, b.x) && MathUtils3D.nearEqual(this.y, b.y) && MathUtils3D.nearEqual(this.z, b.z) && MathUtils3D.nearEqual(this.w, b.w);
|
||
}
|
||
static rotationLookAt(forward, up, out) {
|
||
Quaternion.lookAt(Vector3._ZERO, forward, up, out);
|
||
}
|
||
static lookAt(eye, target, up, out) {
|
||
Matrix3x3.lookAt(eye, target, up, Quaternion._tempMatrix3x3);
|
||
Quaternion.rotationMatrix(Quaternion._tempMatrix3x3, out);
|
||
}
|
||
lengthSquared() {
|
||
return (this.x * this.x) + (this.y * this.y) + (this.z * this.z) + (this.w * this.w);
|
||
}
|
||
static invert(value, out) {
|
||
var lengthSq = value.lengthSquared();
|
||
if (!MathUtils3D.isZero(lengthSq)) {
|
||
lengthSq = 1.0 / lengthSq;
|
||
out.x = -value.x * lengthSq;
|
||
out.y = -value.y * lengthSq;
|
||
out.z = -value.z * lengthSq;
|
||
out.w = value.w * lengthSq;
|
||
}
|
||
}
|
||
static rotationMatrix(matrix3x3, out) {
|
||
var me = matrix3x3.elements;
|
||
var m11 = me[0];
|
||
var m12 = me[1];
|
||
var m13 = me[2];
|
||
var m21 = me[3];
|
||
var m22 = me[4];
|
||
var m23 = me[5];
|
||
var m31 = me[6];
|
||
var m32 = me[7];
|
||
var m33 = me[8];
|
||
var sqrt, half;
|
||
var scale = m11 + m22 + m33;
|
||
if (scale > 0) {
|
||
sqrt = Math.sqrt(scale + 1);
|
||
out.w = sqrt * 0.5;
|
||
sqrt = 0.5 / sqrt;
|
||
out.x = (m23 - m32) * sqrt;
|
||
out.y = (m31 - m13) * sqrt;
|
||
out.z = (m12 - m21) * sqrt;
|
||
}
|
||
else if ((m11 >= m22) && (m11 >= m33)) {
|
||
sqrt = Math.sqrt(1 + m11 - m22 - m33);
|
||
half = 0.5 / sqrt;
|
||
out.x = 0.5 * sqrt;
|
||
out.y = (m12 + m21) * half;
|
||
out.z = (m13 + m31) * half;
|
||
out.w = (m23 - m32) * half;
|
||
}
|
||
else if (m22 > m33) {
|
||
sqrt = Math.sqrt(1 + m22 - m11 - m33);
|
||
half = 0.5 / sqrt;
|
||
out.x = (m21 + m12) * half;
|
||
out.y = 0.5 * sqrt;
|
||
out.z = (m32 + m23) * half;
|
||
out.w = (m31 - m13) * half;
|
||
}
|
||
else {
|
||
sqrt = Math.sqrt(1 + m33 - m11 - m22);
|
||
half = 0.5 / sqrt;
|
||
out.x = (m31 + m13) * half;
|
||
out.y = (m32 + m23) * half;
|
||
out.z = 0.5 * sqrt;
|
||
out.w = (m12 - m21) * half;
|
||
}
|
||
}
|
||
forNativeElement(nativeElements = null) {
|
||
if (nativeElements) {
|
||
this.elements = nativeElements;
|
||
this.elements[0] = this.x;
|
||
this.elements[1] = this.y;
|
||
this.elements[2] = this.z;
|
||
this.elements[3] = this.w;
|
||
}
|
||
else {
|
||
this.elements = new Float32Array([this.x, this.y, this.z, this.w]);
|
||
}
|
||
Vector2.rewriteNumProperty(this, "x", 0);
|
||
Vector2.rewriteNumProperty(this, "y", 1);
|
||
Vector2.rewriteNumProperty(this, "z", 2);
|
||
Vector2.rewriteNumProperty(this, "w", 3);
|
||
}
|
||
}
|
||
Quaternion.TEMPVector30 = new Vector3();
|
||
Quaternion.TEMPVector31 = new Vector3();
|
||
Quaternion.TEMPVector32 = new Vector3();
|
||
Quaternion.TEMPVector33 = new Vector3();
|
||
Quaternion._tempMatrix3x3 = new Matrix3x3();
|
||
Quaternion.DEFAULT = new Quaternion();
|
||
Quaternion.NAN = new Quaternion(NaN, NaN, NaN, NaN);
|
||
|
||
class QuaternionKeyframe extends Keyframe {
|
||
constructor() {
|
||
super();
|
||
this.inTangent = new Vector4();
|
||
this.outTangent = new Vector4();
|
||
this.value = new Quaternion();
|
||
}
|
||
cloneTo(dest) {
|
||
super.cloneTo(dest);
|
||
var destKeyFarme = dest;
|
||
this.inTangent.cloneTo(destKeyFarme.inTangent);
|
||
this.outTangent.cloneTo(destKeyFarme.outTangent);
|
||
this.value.cloneTo(destKeyFarme.value);
|
||
}
|
||
}
|
||
|
||
class Vector3Keyframe extends Keyframe {
|
||
constructor() {
|
||
super();
|
||
this.inTangent = new Vector3();
|
||
this.outTangent = new Vector3();
|
||
this.value = new Vector3();
|
||
}
|
||
cloneTo(dest) {
|
||
super.cloneTo(dest);
|
||
var destKeyFarme = dest;
|
||
this.inTangent.cloneTo(destKeyFarme.inTangent);
|
||
this.outTangent.cloneTo(destKeyFarme.outTangent);
|
||
this.value.cloneTo(destKeyFarme.value);
|
||
}
|
||
}
|
||
|
||
class AnimationClipParser03 {
|
||
static READ_DATA() {
|
||
AnimationClipParser03._DATA.offset = AnimationClipParser03._reader.getUint32();
|
||
AnimationClipParser03._DATA.size = AnimationClipParser03._reader.getUint32();
|
||
}
|
||
static READ_BLOCK() {
|
||
var count = AnimationClipParser03._BLOCK.count = AnimationClipParser03._reader.getUint16();
|
||
var blockStarts = AnimationClipParser03._BLOCK.blockStarts = [];
|
||
var blockLengths = AnimationClipParser03._BLOCK.blockLengths = [];
|
||
for (var i = 0; i < count; i++) {
|
||
blockStarts.push(AnimationClipParser03._reader.getUint32());
|
||
blockLengths.push(AnimationClipParser03._reader.getUint32());
|
||
}
|
||
}
|
||
static READ_STRINGS() {
|
||
var offset = AnimationClipParser03._reader.getUint32();
|
||
var count = AnimationClipParser03._reader.getUint16();
|
||
var prePos = AnimationClipParser03._reader.pos;
|
||
AnimationClipParser03._reader.pos = offset + AnimationClipParser03._DATA.offset;
|
||
for (var i = 0; i < count; i++)
|
||
AnimationClipParser03._strings[i] = AnimationClipParser03._reader.readUTFString();
|
||
AnimationClipParser03._reader.pos = prePos;
|
||
}
|
||
static parse(clip, reader) {
|
||
AnimationClipParser03._animationClip = clip;
|
||
AnimationClipParser03._reader = reader;
|
||
AnimationClipParser03.READ_DATA();
|
||
AnimationClipParser03.READ_BLOCK();
|
||
AnimationClipParser03.READ_STRINGS();
|
||
for (var i = 0, n = AnimationClipParser03._BLOCK.count; i < n; i++) {
|
||
var index = reader.getUint16();
|
||
var blockName = AnimationClipParser03._strings[index];
|
||
var fn = AnimationClipParser03["READ_" + blockName];
|
||
if (fn == null)
|
||
throw new Error("model file err,no this function:" + index + " " + blockName);
|
||
else
|
||
fn.call(null);
|
||
}
|
||
}
|
||
static READ_ANIMATIONS() {
|
||
var i, j;
|
||
var node;
|
||
var reader = AnimationClipParser03._reader;
|
||
var startTimeTypes = [];
|
||
var startTimeTypeCount = reader.getUint16();
|
||
startTimeTypes.length = startTimeTypeCount;
|
||
for (i = 0; i < startTimeTypeCount; i++)
|
||
startTimeTypes[i] = reader.getFloat32();
|
||
var clip = AnimationClipParser03._animationClip;
|
||
clip.name = AnimationClipParser03._strings[reader.getUint16()];
|
||
var clipDur = clip._duration = reader.getFloat32();
|
||
clip.islooping = !!reader.getByte();
|
||
clip._frameRate = reader.getInt16();
|
||
var nodeCount = reader.getInt16();
|
||
var nodes = clip._nodes;
|
||
nodes.count = nodeCount;
|
||
var nodesMap = clip._nodesMap = {};
|
||
var nodesDic = clip._nodesDic = {};
|
||
for (i = 0; i < nodeCount; i++) {
|
||
node = new KeyframeNode();
|
||
nodes.setNodeByIndex(i, node);
|
||
node._indexInList = i;
|
||
var type = node.type = reader.getUint8();
|
||
var pathLength = reader.getUint16();
|
||
node._setOwnerPathCount(pathLength);
|
||
for (j = 0; j < pathLength; j++)
|
||
node._setOwnerPathByIndex(j, AnimationClipParser03._strings[reader.getUint16()]);
|
||
var nodePath = node._joinOwnerPath("/");
|
||
var mapArray = nodesMap[nodePath];
|
||
(mapArray) || (nodesMap[nodePath] = mapArray = []);
|
||
mapArray.push(node);
|
||
node.propertyOwner = AnimationClipParser03._strings[reader.getUint16()];
|
||
var propertyLength = reader.getUint16();
|
||
node._setPropertyCount(propertyLength);
|
||
for (j = 0; j < propertyLength; j++)
|
||
node._setPropertyByIndex(j, AnimationClipParser03._strings[reader.getUint16()]);
|
||
var fullPath = nodePath + "." + node.propertyOwner + "." + node._joinProperty(".");
|
||
nodesDic[fullPath] = node;
|
||
node.fullPath = fullPath;
|
||
var keyframeCount = reader.getUint16();
|
||
node._setKeyframeCount(keyframeCount);
|
||
for (j = 0; j < keyframeCount; j++) {
|
||
switch (type) {
|
||
case 0:
|
||
var floatKeyframe = new FloatKeyframe();
|
||
node._setKeyframeByIndex(j, floatKeyframe);
|
||
floatKeyframe.time = startTimeTypes[reader.getUint16()];
|
||
floatKeyframe.inTangent = reader.getFloat32();
|
||
floatKeyframe.outTangent = reader.getFloat32();
|
||
floatKeyframe.value = reader.getFloat32();
|
||
break;
|
||
case 1:
|
||
case 3:
|
||
case 4:
|
||
var floatArrayKeyframe = new Vector3Keyframe();
|
||
node._setKeyframeByIndex(j, floatArrayKeyframe);
|
||
floatArrayKeyframe.time = startTimeTypes[reader.getUint16()];
|
||
var inTangent = floatArrayKeyframe.inTangent;
|
||
var outTangent = floatArrayKeyframe.outTangent;
|
||
var value = floatArrayKeyframe.value;
|
||
inTangent.x = reader.getFloat32();
|
||
inTangent.y = reader.getFloat32();
|
||
inTangent.z = reader.getFloat32();
|
||
outTangent.x = reader.getFloat32();
|
||
outTangent.y = reader.getFloat32();
|
||
outTangent.z = reader.getFloat32();
|
||
value.x = reader.getFloat32();
|
||
value.y = reader.getFloat32();
|
||
value.z = reader.getFloat32();
|
||
break;
|
||
case 2:
|
||
var quaArrayKeyframe = new QuaternionKeyframe();
|
||
node._setKeyframeByIndex(j, quaArrayKeyframe);
|
||
quaArrayKeyframe.time = startTimeTypes[reader.getUint16()];
|
||
var inTangentQua = quaArrayKeyframe.inTangent;
|
||
var outTangentQua = quaArrayKeyframe.outTangent;
|
||
var valueQua = quaArrayKeyframe.value;
|
||
inTangentQua.x = reader.getFloat32();
|
||
inTangentQua.y = reader.getFloat32();
|
||
inTangentQua.z = reader.getFloat32();
|
||
inTangentQua.w = reader.getFloat32();
|
||
outTangentQua.x = reader.getFloat32();
|
||
outTangentQua.y = reader.getFloat32();
|
||
outTangentQua.z = reader.getFloat32();
|
||
outTangentQua.w = reader.getFloat32();
|
||
valueQua.x = reader.getFloat32();
|
||
valueQua.y = reader.getFloat32();
|
||
valueQua.z = reader.getFloat32();
|
||
valueQua.w = reader.getFloat32();
|
||
break;
|
||
default:
|
||
throw "AnimationClipParser03:unknown type.";
|
||
}
|
||
}
|
||
}
|
||
var eventCount = reader.getUint16();
|
||
for (i = 0; i < eventCount; i++) {
|
||
var event = new AnimationEvent();
|
||
event.time = Math.min(clipDur, reader.getFloat32());
|
||
event.eventName = AnimationClipParser03._strings[reader.getUint16()];
|
||
var params = [];
|
||
var paramCount = reader.getUint16();
|
||
(paramCount > 0) && (event.params = params = []);
|
||
for (j = 0; j < paramCount; j++) {
|
||
var eventType = reader.getByte();
|
||
switch (eventType) {
|
||
case 0:
|
||
params.push(!!reader.getByte());
|
||
break;
|
||
case 1:
|
||
params.push(reader.getInt32());
|
||
break;
|
||
case 2:
|
||
params.push(reader.getFloat32());
|
||
break;
|
||
case 3:
|
||
params.push(AnimationClipParser03._strings[reader.getUint16()]);
|
||
break;
|
||
default:
|
||
throw new Error("unknown type.");
|
||
}
|
||
}
|
||
clip.addEvent(event);
|
||
}
|
||
}
|
||
}
|
||
AnimationClipParser03._strings = [];
|
||
AnimationClipParser03._BLOCK = { count: 0 };
|
||
AnimationClipParser03._DATA = { offset: 0, size: 0 };
|
||
|
||
class AnimationClipParser04 {
|
||
static READ_DATA() {
|
||
AnimationClipParser04._DATA.offset = AnimationClipParser04._reader.getUint32();
|
||
AnimationClipParser04._DATA.size = AnimationClipParser04._reader.getUint32();
|
||
}
|
||
static READ_BLOCK() {
|
||
var count = AnimationClipParser04._BLOCK.count = AnimationClipParser04._reader.getUint16();
|
||
var blockStarts = AnimationClipParser04._BLOCK.blockStarts = [];
|
||
var blockLengths = AnimationClipParser04._BLOCK.blockLengths = [];
|
||
for (var i = 0; i < count; i++) {
|
||
blockStarts.push(AnimationClipParser04._reader.getUint32());
|
||
blockLengths.push(AnimationClipParser04._reader.getUint32());
|
||
}
|
||
}
|
||
static READ_STRINGS() {
|
||
var offset = AnimationClipParser04._reader.getUint32();
|
||
var count = AnimationClipParser04._reader.getUint16();
|
||
var prePos = AnimationClipParser04._reader.pos;
|
||
AnimationClipParser04._reader.pos = offset + AnimationClipParser04._DATA.offset;
|
||
for (var i = 0; i < count; i++)
|
||
AnimationClipParser04._strings[i] = AnimationClipParser04._reader.readUTFString();
|
||
AnimationClipParser04._reader.pos = prePos;
|
||
}
|
||
static parse(clip, reader, version) {
|
||
AnimationClipParser04._animationClip = clip;
|
||
AnimationClipParser04._reader = reader;
|
||
AnimationClipParser04._version = version;
|
||
AnimationClipParser04.READ_DATA();
|
||
AnimationClipParser04.READ_BLOCK();
|
||
AnimationClipParser04.READ_STRINGS();
|
||
for (var i = 0, n = AnimationClipParser04._BLOCK.count; i < n; i++) {
|
||
var index = reader.getUint16();
|
||
var blockName = AnimationClipParser04._strings[index];
|
||
var fn = AnimationClipParser04["READ_" + blockName];
|
||
if (fn == null)
|
||
throw new Error("model file err,no this function:" + index + " " + blockName);
|
||
else
|
||
fn.call(null);
|
||
}
|
||
AnimationClipParser04._version = null;
|
||
AnimationClipParser04._reader = null;
|
||
AnimationClipParser04._animationClip = null;
|
||
}
|
||
static READ_ANIMATIONS() {
|
||
var i, j;
|
||
var node;
|
||
var reader = AnimationClipParser04._reader;
|
||
var startTimeTypes = [];
|
||
var startTimeTypeCount = reader.getUint16();
|
||
startTimeTypes.length = startTimeTypeCount;
|
||
for (i = 0; i < startTimeTypeCount; i++)
|
||
startTimeTypes[i] = reader.getFloat32();
|
||
var clip = AnimationClipParser04._animationClip;
|
||
clip.name = AnimationClipParser04._strings[reader.getUint16()];
|
||
var clipDur = clip._duration = reader.getFloat32();
|
||
clip.islooping = !!reader.getByte();
|
||
clip._frameRate = reader.getInt16();
|
||
var nodeCount = reader.getInt16();
|
||
var nodes = clip._nodes;
|
||
nodes.count = nodeCount;
|
||
var nodesMap = clip._nodesMap = {};
|
||
var nodesDic = clip._nodesDic = {};
|
||
for (i = 0; i < nodeCount; i++) {
|
||
node = new KeyframeNode();
|
||
nodes.setNodeByIndex(i, node);
|
||
node._indexInList = i;
|
||
var type = node.type = reader.getUint8();
|
||
var pathLength = reader.getUint16();
|
||
node._setOwnerPathCount(pathLength);
|
||
for (j = 0; j < pathLength; j++)
|
||
node._setOwnerPathByIndex(j, AnimationClipParser04._strings[reader.getUint16()]);
|
||
var nodePath = node._joinOwnerPath("/");
|
||
var mapArray = nodesMap[nodePath];
|
||
(mapArray) || (nodesMap[nodePath] = mapArray = []);
|
||
mapArray.push(node);
|
||
node.propertyOwner = AnimationClipParser04._strings[reader.getUint16()];
|
||
var propertyLength = reader.getUint16();
|
||
node._setPropertyCount(propertyLength);
|
||
for (j = 0; j < propertyLength; j++)
|
||
node._setPropertyByIndex(j, AnimationClipParser04._strings[reader.getUint16()]);
|
||
var fullPath = nodePath + "." + node.propertyOwner + "." + node._joinProperty(".");
|
||
nodesDic[fullPath] = node;
|
||
node.fullPath = fullPath;
|
||
node.nodePath = nodePath;
|
||
var keyframeCount = reader.getUint16();
|
||
node._setKeyframeCount(keyframeCount);
|
||
switch (AnimationClipParser04._version) {
|
||
case "LAYAANIMATION:04":
|
||
for (j = 0; j < keyframeCount; j++) {
|
||
switch (type) {
|
||
case 0:
|
||
var floatKeyframe = new FloatKeyframe();
|
||
node._setKeyframeByIndex(j, floatKeyframe);
|
||
floatKeyframe.time = startTimeTypes[reader.getUint16()];
|
||
floatKeyframe.inTangent = reader.getFloat32();
|
||
floatKeyframe.outTangent = reader.getFloat32();
|
||
floatKeyframe.value = reader.getFloat32();
|
||
break;
|
||
case 1:
|
||
case 3:
|
||
case 4:
|
||
var floatArrayKeyframe = new Vector3Keyframe();
|
||
node._setKeyframeByIndex(j, floatArrayKeyframe);
|
||
floatArrayKeyframe.time = startTimeTypes[reader.getUint16()];
|
||
var inTangent = floatArrayKeyframe.inTangent;
|
||
var outTangent = floatArrayKeyframe.outTangent;
|
||
var value = floatArrayKeyframe.value;
|
||
inTangent.x = reader.getFloat32();
|
||
inTangent.y = reader.getFloat32();
|
||
inTangent.z = reader.getFloat32();
|
||
outTangent.x = reader.getFloat32();
|
||
outTangent.y = reader.getFloat32();
|
||
outTangent.z = reader.getFloat32();
|
||
value.x = reader.getFloat32();
|
||
value.y = reader.getFloat32();
|
||
value.z = reader.getFloat32();
|
||
break;
|
||
case 2:
|
||
var quaternionKeyframe = new QuaternionKeyframe();
|
||
node._setKeyframeByIndex(j, quaternionKeyframe);
|
||
quaternionKeyframe.time = startTimeTypes[reader.getUint16()];
|
||
var inTangentQua = quaternionKeyframe.inTangent;
|
||
var outTangentQua = quaternionKeyframe.outTangent;
|
||
var valueQua = quaternionKeyframe.value;
|
||
inTangentQua.x = reader.getFloat32();
|
||
inTangentQua.y = reader.getFloat32();
|
||
inTangentQua.z = reader.getFloat32();
|
||
inTangentQua.w = reader.getFloat32();
|
||
outTangentQua.x = reader.getFloat32();
|
||
outTangentQua.y = reader.getFloat32();
|
||
outTangentQua.z = reader.getFloat32();
|
||
outTangentQua.w = reader.getFloat32();
|
||
valueQua.x = reader.getFloat32();
|
||
valueQua.y = reader.getFloat32();
|
||
valueQua.z = reader.getFloat32();
|
||
valueQua.w = reader.getFloat32();
|
||
break;
|
||
default:
|
||
throw "AnimationClipParser04:unknown type.";
|
||
}
|
||
}
|
||
break;
|
||
case "LAYAANIMATION:COMPRESSION_04":
|
||
for (j = 0; j < keyframeCount; j++) {
|
||
switch (type) {
|
||
case 0:
|
||
floatKeyframe = new FloatKeyframe();
|
||
node._setKeyframeByIndex(j, floatKeyframe);
|
||
floatKeyframe.time = startTimeTypes[reader.getUint16()];
|
||
floatKeyframe.inTangent = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
floatKeyframe.outTangent = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
floatKeyframe.value = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
break;
|
||
case 1:
|
||
case 3:
|
||
case 4:
|
||
floatArrayKeyframe = new Vector3Keyframe();
|
||
node._setKeyframeByIndex(j, floatArrayKeyframe);
|
||
floatArrayKeyframe.time = startTimeTypes[reader.getUint16()];
|
||
inTangent = floatArrayKeyframe.inTangent;
|
||
outTangent = floatArrayKeyframe.outTangent;
|
||
value = floatArrayKeyframe.value;
|
||
inTangent.x = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
inTangent.y = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
inTangent.z = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
outTangent.x = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
outTangent.y = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
outTangent.z = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
value.x = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
value.y = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
value.z = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
break;
|
||
case 2:
|
||
quaternionKeyframe = new QuaternionKeyframe();
|
||
node._setKeyframeByIndex(j, quaternionKeyframe);
|
||
quaternionKeyframe.time = startTimeTypes[reader.getUint16()];
|
||
inTangentQua = quaternionKeyframe.inTangent;
|
||
outTangentQua = quaternionKeyframe.outTangent;
|
||
valueQua = quaternionKeyframe.value;
|
||
inTangentQua.x = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
inTangentQua.y = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
inTangentQua.z = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
inTangentQua.w = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
outTangentQua.x = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
outTangentQua.y = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
outTangentQua.z = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
outTangentQua.w = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
valueQua.x = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
valueQua.y = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
valueQua.z = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
valueQua.w = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
break;
|
||
default:
|
||
throw "AnimationClipParser04:unknown type.";
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
var eventCount = reader.getUint16();
|
||
for (i = 0; i < eventCount; i++) {
|
||
var event = new AnimationEvent();
|
||
event.time = Math.min(clipDur, reader.getFloat32());
|
||
event.eventName = AnimationClipParser04._strings[reader.getUint16()];
|
||
var params = [];
|
||
var paramCount = reader.getUint16();
|
||
(paramCount > 0) && (event.params = params = []);
|
||
for (j = 0; j < paramCount; j++) {
|
||
var eventType = reader.getByte();
|
||
switch (eventType) {
|
||
case 0:
|
||
params.push(!!reader.getByte());
|
||
break;
|
||
case 1:
|
||
params.push(reader.getInt32());
|
||
break;
|
||
case 2:
|
||
params.push(reader.getFloat32());
|
||
break;
|
||
case 3:
|
||
params.push(AnimationClipParser04._strings[reader.getUint16()]);
|
||
break;
|
||
default:
|
||
throw new Error("unknown type.");
|
||
}
|
||
}
|
||
clip.addEvent(event);
|
||
}
|
||
}
|
||
}
|
||
AnimationClipParser04._strings = [];
|
||
AnimationClipParser04._BLOCK = { count: 0 };
|
||
AnimationClipParser04._DATA = { offset: 0, size: 0 };
|
||
|
||
class KeyframeNodeList {
|
||
constructor() {
|
||
this._nodes = [];
|
||
}
|
||
get count() {
|
||
return this._nodes.length;
|
||
}
|
||
set count(value) {
|
||
this._nodes.length = value;
|
||
}
|
||
getNodeByIndex(index) {
|
||
return this._nodes[index];
|
||
}
|
||
setNodeByIndex(index, node) {
|
||
this._nodes[index] = node;
|
||
}
|
||
}
|
||
|
||
class TextureGenerator {
|
||
constructor() {
|
||
}
|
||
static lightAttenTexture(x, y, maxX, maxY, index, data) {
|
||
var sqrRange = x / maxX;
|
||
var atten = 1.0 / (1.0 + 25.0 * sqrRange);
|
||
if (sqrRange >= 0.64) {
|
||
if (sqrRange > 1.0) {
|
||
atten = 0;
|
||
}
|
||
else {
|
||
atten *= 1 - (sqrRange - 0.64) / (1 - 0.64);
|
||
}
|
||
}
|
||
data[index] = Math.floor(atten * 255.0 + 0.5);
|
||
}
|
||
static haloTexture(x, y, maxX, maxY, index, data) {
|
||
maxX >>= 1;
|
||
maxY >>= 1;
|
||
var xFac = (x - maxX) / maxX;
|
||
var yFac = (y - maxY) / maxY;
|
||
var sqrRange = xFac * xFac + yFac * yFac;
|
||
if (sqrRange > 1.0) {
|
||
sqrRange = 1.0;
|
||
}
|
||
data[index] = Math.floor((1.0 - sqrRange) * 255.0 + 0.5);
|
||
}
|
||
static _generateTexture2D(texture, textureWidth, textureHeight, func) {
|
||
var index = 0;
|
||
var size = 0;
|
||
switch (texture.format) {
|
||
case Laya.TextureFormat.R8G8B8:
|
||
size = 3;
|
||
break;
|
||
case Laya.TextureFormat.R8G8B8A8:
|
||
size = 4;
|
||
break;
|
||
case Laya.TextureFormat.Alpha8:
|
||
size = 1;
|
||
break;
|
||
default:
|
||
throw "GeneratedTexture._generateTexture: unkonw texture format.";
|
||
}
|
||
var data = new Uint8Array(textureWidth * textureHeight * size);
|
||
for (var y = 0; y < textureHeight; y++) {
|
||
for (var x = 0; x < textureWidth; x++) {
|
||
func(x, y, textureWidth, textureHeight, index, data);
|
||
index += size;
|
||
}
|
||
}
|
||
texture.setPixels(data);
|
||
}
|
||
}
|
||
|
||
class Utils3D {
|
||
static _createFloatTextureBuffer(width, height) {
|
||
var floatTex = new Laya.Texture2D(width, height, Laya.TextureFormat.R32G32B32A32, false, false);
|
||
floatTex.filterMode = Laya.FilterMode.Point;
|
||
floatTex.wrapModeU = Laya.WarpMode.Clamp;
|
||
floatTex.wrapModeV = Laya.WarpMode.Clamp;
|
||
floatTex.anisoLevel = 0;
|
||
return floatTex;
|
||
}
|
||
static _convertToLayaVec3(bVector, out, inverseX) {
|
||
var bullet = ILaya3D.Physics3D._bullet;
|
||
out.x = inverseX ? -bullet.btVector3_x(bVector) : bullet.btVector3_x(bVector);
|
||
out.y = bullet.btVector3_y(bVector);
|
||
out.z = bullet.btVector3_z(bVector);
|
||
}
|
||
static _convertToBulletVec3(lVector, out, inverseX) {
|
||
ILaya3D.Physics3D._bullet.btVector3_setValue(out, inverseX ? -lVector.x : lVector.x, lVector.y, lVector.z);
|
||
}
|
||
static _rotationTransformScaleSkinAnimation(tx, ty, tz, qx, qy, qz, qw, sx, sy, sz, outArray, outOffset) {
|
||
var re = Utils3D._tempArray16_0;
|
||
var se = Utils3D._tempArray16_1;
|
||
var tse = Utils3D._tempArray16_2;
|
||
var x2 = qx + qx;
|
||
var y2 = qy + qy;
|
||
var z2 = qz + qz;
|
||
var xx = qx * x2;
|
||
var yx = qy * x2;
|
||
var yy = qy * y2;
|
||
var zx = qz * x2;
|
||
var zy = qz * y2;
|
||
var zz = qz * z2;
|
||
var wx = qw * x2;
|
||
var wy = qw * y2;
|
||
var wz = qw * z2;
|
||
re[15] = 1;
|
||
re[0] = 1 - yy - zz;
|
||
re[1] = yx + wz;
|
||
re[2] = zx - wy;
|
||
re[4] = yx - wz;
|
||
re[5] = 1 - xx - zz;
|
||
re[6] = zy + wx;
|
||
re[8] = zx + wy;
|
||
re[9] = zy - wx;
|
||
re[10] = 1 - xx - yy;
|
||
se[15] = 1;
|
||
se[0] = sx;
|
||
se[5] = sy;
|
||
se[10] = sz;
|
||
var i, ai0, ai1, ai2, ai3;
|
||
for (i = 0; i < 4; i++) {
|
||
ai0 = re[i];
|
||
ai1 = re[i + 4];
|
||
ai2 = re[i + 8];
|
||
ai3 = re[i + 12];
|
||
tse[i] = ai0;
|
||
tse[i + 4] = ai1;
|
||
tse[i + 8] = ai2;
|
||
tse[i + 12] = ai0 * tx + ai1 * ty + ai2 * tz + ai3;
|
||
}
|
||
for (i = 0; i < 4; i++) {
|
||
ai0 = tse[i];
|
||
ai1 = tse[i + 4];
|
||
ai2 = tse[i + 8];
|
||
ai3 = tse[i + 12];
|
||
outArray[i + outOffset] = ai0 * se[0] + ai1 * se[1] + ai2 * se[2] + ai3 * se[3];
|
||
outArray[i + outOffset + 4] = ai0 * se[4] + ai1 * se[5] + ai2 * se[6] + ai3 * se[7];
|
||
outArray[i + outOffset + 8] = ai0 * se[8] + ai1 * se[9] + ai2 * se[10] + ai3 * se[11];
|
||
outArray[i + outOffset + 12] = ai0 * se[12] + ai1 * se[13] + ai2 * se[14] + ai3 * se[15];
|
||
}
|
||
}
|
||
static _computeBoneAndAnimationDatasByBindPoseMatrxix(bones, curData, inverGlobalBindPose, outBonesDatas, outAnimationDatas, boneIndexToMesh) {
|
||
var offset = 0;
|
||
var matOffset = 0;
|
||
var i;
|
||
var parentOffset;
|
||
var boneLength = bones.length;
|
||
for (i = 0; i < boneLength; offset += bones[i].keyframeWidth, matOffset += 16, i++) {
|
||
Utils3D._rotationTransformScaleSkinAnimation(curData[offset + 0], curData[offset + 1], curData[offset + 2], curData[offset + 3], curData[offset + 4], curData[offset + 5], curData[offset + 6], curData[offset + 7], curData[offset + 8], curData[offset + 9], outBonesDatas, matOffset);
|
||
if (i != 0) {
|
||
parentOffset = bones[i].parentIndex * 16;
|
||
Utils3D.mulMatrixByArray(outBonesDatas, parentOffset, outBonesDatas, matOffset, outBonesDatas, matOffset);
|
||
}
|
||
}
|
||
var n = inverGlobalBindPose.length;
|
||
for (i = 0; i < n; i++) {
|
||
Utils3D.mulMatrixByArrayAndMatrixFast(outBonesDatas, boneIndexToMesh[i] * 16, inverGlobalBindPose[i], outAnimationDatas, i * 16);
|
||
}
|
||
}
|
||
static _computeAnimationDatasByArrayAndMatrixFast(inverGlobalBindPose, bonesDatas, outAnimationDatas, boneIndexToMesh) {
|
||
for (var i = 0, n = inverGlobalBindPose.length; i < n; i++)
|
||
Utils3D.mulMatrixByArrayAndMatrixFast(bonesDatas, boneIndexToMesh[i] * 16, inverGlobalBindPose[i], outAnimationDatas, i * 16);
|
||
}
|
||
static _computeBoneAndAnimationDatasByBindPoseMatrxixOld(bones, curData, inverGlobalBindPose, outBonesDatas, outAnimationDatas) {
|
||
var offset = 0;
|
||
var matOffset = 0;
|
||
var i;
|
||
var parentOffset;
|
||
var boneLength = bones.length;
|
||
for (i = 0; i < boneLength; offset += bones[i].keyframeWidth, matOffset += 16, i++) {
|
||
Utils3D._rotationTransformScaleSkinAnimation(curData[offset + 7], curData[offset + 8], curData[offset + 9], curData[offset + 3], curData[offset + 4], curData[offset + 5], curData[offset + 6], curData[offset + 0], curData[offset + 1], curData[offset + 2], outBonesDatas, matOffset);
|
||
if (i != 0) {
|
||
parentOffset = bones[i].parentIndex * 16;
|
||
Utils3D.mulMatrixByArray(outBonesDatas, parentOffset, outBonesDatas, matOffset, outBonesDatas, matOffset);
|
||
}
|
||
}
|
||
var n = inverGlobalBindPose.length;
|
||
for (i = 0; i < n; i++) {
|
||
var arrayOffset = i * 16;
|
||
Utils3D.mulMatrixByArrayAndMatrixFast(outBonesDatas, arrayOffset, inverGlobalBindPose[i], outAnimationDatas, arrayOffset);
|
||
}
|
||
}
|
||
static _computeAnimationDatasByArrayAndMatrixFastOld(inverGlobalBindPose, bonesDatas, outAnimationDatas) {
|
||
var n = inverGlobalBindPose.length;
|
||
for (var i = 0; i < n; i++) {
|
||
var arrayOffset = i * 16;
|
||
Utils3D.mulMatrixByArrayAndMatrixFast(bonesDatas, arrayOffset, inverGlobalBindPose[i], outAnimationDatas, arrayOffset);
|
||
}
|
||
}
|
||
static _computeRootAnimationData(bones, curData, animationDatas) {
|
||
for (var i = 0, offset = 0, matOffset = 0, boneLength = bones.length; i < boneLength; offset += bones[i].keyframeWidth, matOffset += 16, i++)
|
||
Utils3D.createAffineTransformationArray(curData[offset + 0], curData[offset + 1], curData[offset + 2], curData[offset + 3], curData[offset + 4], curData[offset + 5], curData[offset + 6], curData[offset + 7], curData[offset + 8], curData[offset + 9], animationDatas, matOffset);
|
||
}
|
||
static transformVector3ArrayByQuat(sourceArray, sourceOffset, rotation, outArray, outOffset) {
|
||
var x = sourceArray[sourceOffset], y = sourceArray[sourceOffset + 1], z = sourceArray[sourceOffset + 2], qx = rotation.x, qy = rotation.y, qz = rotation.z, qw = rotation.w, ix = qw * x + qy * z - qz * y, iy = qw * y + qz * x - qx * z, iz = qw * z + qx * y - qy * x, iw = -qx * x - qy * y - qz * z;
|
||
outArray[outOffset] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
|
||
outArray[outOffset + 1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
|
||
outArray[outOffset + 2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
|
||
}
|
||
static mulMatrixByArray(leftArray, leftOffset, rightArray, rightOffset, outArray, outOffset) {
|
||
var i, ai0, ai1, ai2, ai3;
|
||
if (outArray === rightArray) {
|
||
rightArray = Utils3D._tempArray16_3;
|
||
for (i = 0; i < 16; ++i) {
|
||
rightArray[i] = outArray[outOffset + i];
|
||
}
|
||
rightOffset = 0;
|
||
}
|
||
for (i = 0; i < 4; i++) {
|
||
ai0 = leftArray[leftOffset + i];
|
||
ai1 = leftArray[leftOffset + i + 4];
|
||
ai2 = leftArray[leftOffset + i + 8];
|
||
ai3 = leftArray[leftOffset + i + 12];
|
||
outArray[outOffset + i] = ai0 * rightArray[rightOffset + 0] + ai1 * rightArray[rightOffset + 1] + ai2 * rightArray[rightOffset + 2] + ai3 * rightArray[rightOffset + 3];
|
||
outArray[outOffset + i + 4] = ai0 * rightArray[rightOffset + 4] + ai1 * rightArray[rightOffset + 5] + ai2 * rightArray[rightOffset + 6] + ai3 * rightArray[rightOffset + 7];
|
||
outArray[outOffset + i + 8] = ai0 * rightArray[rightOffset + 8] + ai1 * rightArray[rightOffset + 9] + ai2 * rightArray[rightOffset + 10] + ai3 * rightArray[rightOffset + 11];
|
||
outArray[outOffset + i + 12] = ai0 * rightArray[rightOffset + 12] + ai1 * rightArray[rightOffset + 13] + ai2 * rightArray[rightOffset + 14] + ai3 * rightArray[rightOffset + 15];
|
||
}
|
||
}
|
||
static mulMatrixByArrayFast(leftArray, leftOffset, rightArray, rightOffset, outArray, outOffset) {
|
||
var i, ai0, ai1, ai2, ai3;
|
||
for (i = 0; i < 4; i++) {
|
||
ai0 = leftArray[leftOffset + i];
|
||
ai1 = leftArray[leftOffset + i + 4];
|
||
ai2 = leftArray[leftOffset + i + 8];
|
||
ai3 = leftArray[leftOffset + i + 12];
|
||
outArray[outOffset + i] = ai0 * rightArray[rightOffset + 0] + ai1 * rightArray[rightOffset + 1] + ai2 * rightArray[rightOffset + 2] + ai3 * rightArray[rightOffset + 3];
|
||
outArray[outOffset + i + 4] = ai0 * rightArray[rightOffset + 4] + ai1 * rightArray[rightOffset + 5] + ai2 * rightArray[rightOffset + 6] + ai3 * rightArray[rightOffset + 7];
|
||
outArray[outOffset + i + 8] = ai0 * rightArray[rightOffset + 8] + ai1 * rightArray[rightOffset + 9] + ai2 * rightArray[rightOffset + 10] + ai3 * rightArray[rightOffset + 11];
|
||
outArray[outOffset + i + 12] = ai0 * rightArray[rightOffset + 12] + ai1 * rightArray[rightOffset + 13] + ai2 * rightArray[rightOffset + 14] + ai3 * rightArray[rightOffset + 15];
|
||
}
|
||
}
|
||
static mulMatrixByArrayAndMatrixFast(leftArray, leftOffset, rightMatrix, outArray, outOffset) {
|
||
var i, ai0, ai1, ai2, ai3;
|
||
var rightMatrixE = rightMatrix.elements;
|
||
var m11 = rightMatrixE[0], m12 = rightMatrixE[1], m13 = rightMatrixE[2], m14 = rightMatrixE[3];
|
||
var m21 = rightMatrixE[4], m22 = rightMatrixE[5], m23 = rightMatrixE[6], m24 = rightMatrixE[7];
|
||
var m31 = rightMatrixE[8], m32 = rightMatrixE[9], m33 = rightMatrixE[10], m34 = rightMatrixE[11];
|
||
var m41 = rightMatrixE[12], m42 = rightMatrixE[13], m43 = rightMatrixE[14], m44 = rightMatrixE[15];
|
||
var ai0LeftOffset = leftOffset;
|
||
var ai1LeftOffset = leftOffset + 4;
|
||
var ai2LeftOffset = leftOffset + 8;
|
||
var ai3LeftOffset = leftOffset + 12;
|
||
var ai0OutOffset = outOffset;
|
||
var ai1OutOffset = outOffset + 4;
|
||
var ai2OutOffset = outOffset + 8;
|
||
var ai3OutOffset = outOffset + 12;
|
||
for (i = 0; i < 4; i++) {
|
||
ai0 = leftArray[ai0LeftOffset + i];
|
||
ai1 = leftArray[ai1LeftOffset + i];
|
||
ai2 = leftArray[ai2LeftOffset + i];
|
||
ai3 = leftArray[ai3LeftOffset + i];
|
||
outArray[ai0OutOffset + i] = ai0 * m11 + ai1 * m12 + ai2 * m13 + ai3 * m14;
|
||
outArray[ai1OutOffset + i] = ai0 * m21 + ai1 * m22 + ai2 * m23 + ai3 * m24;
|
||
outArray[ai2OutOffset + i] = ai0 * m31 + ai1 * m32 + ai2 * m33 + ai3 * m34;
|
||
outArray[ai3OutOffset + i] = ai0 * m41 + ai1 * m42 + ai2 * m43 + ai3 * m44;
|
||
}
|
||
}
|
||
static createAffineTransformationArray(tX, tY, tZ, rX, rY, rZ, rW, sX, sY, sZ, outArray, outOffset) {
|
||
var x2 = rX + rX, y2 = rY + rY, z2 = rZ + rZ;
|
||
var xx = rX * x2, xy = rX * y2, xz = rX * z2, yy = rY * y2, yz = rY * z2, zz = rZ * z2;
|
||
var wx = rW * x2, wy = rW * y2, wz = rW * z2;
|
||
outArray[outOffset + 0] = (1 - (yy + zz)) * sX;
|
||
outArray[outOffset + 1] = (xy + wz) * sX;
|
||
outArray[outOffset + 2] = (xz - wy) * sX;
|
||
outArray[outOffset + 3] = 0;
|
||
outArray[outOffset + 4] = (xy - wz) * sY;
|
||
outArray[outOffset + 5] = (1 - (xx + zz)) * sY;
|
||
outArray[outOffset + 6] = (yz + wx) * sY;
|
||
outArray[outOffset + 7] = 0;
|
||
outArray[outOffset + 8] = (xz + wy) * sZ;
|
||
outArray[outOffset + 9] = (yz - wx) * sZ;
|
||
outArray[outOffset + 10] = (1 - (xx + yy)) * sZ;
|
||
outArray[outOffset + 11] = 0;
|
||
outArray[outOffset + 12] = tX;
|
||
outArray[outOffset + 13] = tY;
|
||
outArray[outOffset + 14] = tZ;
|
||
outArray[outOffset + 15] = 1;
|
||
}
|
||
static transformVector3ArrayToVector3ArrayCoordinate(source, sourceOffset, transform, result, resultOffset) {
|
||
var coordinateX = source[sourceOffset + 0];
|
||
var coordinateY = source[sourceOffset + 1];
|
||
var coordinateZ = source[sourceOffset + 2];
|
||
var transformElem = transform.elements;
|
||
var w = ((coordinateX * transformElem[3]) + (coordinateY * transformElem[7]) + (coordinateZ * transformElem[11]) + transformElem[15]);
|
||
result[resultOffset] = (coordinateX * transformElem[0]) + (coordinateY * transformElem[4]) + (coordinateZ * transformElem[8]) + transformElem[12] / w;
|
||
result[resultOffset + 1] = (coordinateX * transformElem[1]) + (coordinateY * transformElem[5]) + (coordinateZ * transformElem[9]) + transformElem[13] / w;
|
||
result[resultOffset + 2] = (coordinateX * transformElem[2]) + (coordinateY * transformElem[6]) + (coordinateZ * transformElem[10]) + transformElem[14] / w;
|
||
}
|
||
static transformVector3ArrayToVector3ArrayNormal(source, sourceOffset, transform, result, resultOffset) {
|
||
var coordinateX = source[sourceOffset + 0];
|
||
var coordinateY = source[sourceOffset + 1];
|
||
var coordinateZ = source[sourceOffset + 2];
|
||
var transformElem = transform.elements;
|
||
result[resultOffset] = coordinateX * transformElem[0] + coordinateY * transformElem[4] + coordinateZ * transformElem[8];
|
||
result[resultOffset + 1] = coordinateX * transformElem[1] + coordinateY * transformElem[5] + coordinateZ * transformElem[9];
|
||
result[resultOffset + 2] = coordinateX * transformElem[2] + coordinateY * transformElem[6] + coordinateZ * transformElem[10];
|
||
}
|
||
static transformLightingMapTexcoordArray(source, sourceOffset, lightingMapScaleOffset, result, resultOffset) {
|
||
result[resultOffset + 0] = source[sourceOffset + 0] * lightingMapScaleOffset.x + lightingMapScaleOffset.z;
|
||
result[resultOffset + 1] = 1.0 - ((1.0 - source[sourceOffset + 1]) * lightingMapScaleOffset.y + lightingMapScaleOffset.w);
|
||
}
|
||
static getURLVerion(url) {
|
||
var index = url.indexOf("?");
|
||
return index >= 0 ? url.substr(index) : null;
|
||
}
|
||
static _createAffineTransformationArray(trans, rot, scale, outE) {
|
||
var x = rot.x, y = rot.y, z = rot.z, w = rot.w, x2 = x + x, y2 = y + y, z2 = z + z;
|
||
var xx = x * x2, xy = x * y2, xz = x * z2, yy = y * y2, yz = y * z2, zz = z * z2;
|
||
var wx = w * x2, wy = w * y2, wz = w * z2, sx = scale.x, sy = scale.y, sz = scale.z;
|
||
outE[0] = (1 - (yy + zz)) * sx;
|
||
outE[1] = (xy + wz) * sx;
|
||
outE[2] = (xz - wy) * sx;
|
||
outE[3] = 0;
|
||
outE[4] = (xy - wz) * sy;
|
||
outE[5] = (1 - (xx + zz)) * sy;
|
||
outE[6] = (yz + wx) * sy;
|
||
outE[7] = 0;
|
||
outE[8] = (xz + wy) * sz;
|
||
outE[9] = (yz - wx) * sz;
|
||
outE[10] = (1 - (xx + yy)) * sz;
|
||
outE[11] = 0;
|
||
outE[12] = trans.x;
|
||
outE[13] = trans.y;
|
||
outE[14] = trans.z;
|
||
outE[15] = 1;
|
||
}
|
||
static _mulMatrixArray(left, right, rightOffset, outArray, outOffset) {
|
||
var l = right;
|
||
var r = left;
|
||
var e = outArray;
|
||
var l11 = l[rightOffset], l12 = l[rightOffset + 1], l13 = l[rightOffset + 2], l14 = l[rightOffset + 3];
|
||
var l21 = l[rightOffset + 4], l22 = l[rightOffset + 5], l23 = l[rightOffset + 6], l24 = l[rightOffset + 7];
|
||
var l31 = l[rightOffset + 8], l32 = l[rightOffset + 9], l33 = l[rightOffset + 10], l34 = l[rightOffset + 11];
|
||
var l41 = l[rightOffset + 12], l42 = l[rightOffset + 13], l43 = l[rightOffset + 14], l44 = l[rightOffset + 15];
|
||
var r11 = r[0], r12 = r[1], r13 = r[2], r14 = r[3];
|
||
var r21 = r[4], r22 = r[5], r23 = r[6], r24 = r[7];
|
||
var r31 = r[8], r32 = r[9], r33 = r[10], r34 = r[11];
|
||
var r41 = r[12], r42 = r[13], r43 = r[14], r44 = r[15];
|
||
e[outOffset] = (l11 * r11) + (l12 * r21) + (l13 * r31) + (l14 * r41);
|
||
e[outOffset + 1] = (l11 * r12) + (l12 * r22) + (l13 * r32) + (l14 * r42);
|
||
e[outOffset + 2] = (l11 * r13) + (l12 * r23) + (l13 * r33) + (l14 * r43);
|
||
e[outOffset + 3] = (l11 * r14) + (l12 * r24) + (l13 * r34) + (l14 * r44);
|
||
e[outOffset + 4] = (l21 * r11) + (l22 * r21) + (l23 * r31) + (l24 * r41);
|
||
e[outOffset + 5] = (l21 * r12) + (l22 * r22) + (l23 * r32) + (l24 * r42);
|
||
e[outOffset + 6] = (l21 * r13) + (l22 * r23) + (l23 * r33) + (l24 * r43);
|
||
e[outOffset + 7] = (l21 * r14) + (l22 * r24) + (l23 * r34) + (l24 * r44);
|
||
e[outOffset + 8] = (l31 * r11) + (l32 * r21) + (l33 * r31) + (l34 * r41);
|
||
e[outOffset + 9] = (l31 * r12) + (l32 * r22) + (l33 * r32) + (l34 * r42);
|
||
e[outOffset + 10] = (l31 * r13) + (l32 * r23) + (l33 * r33) + (l34 * r43);
|
||
e[outOffset + 11] = (l31 * r14) + (l32 * r24) + (l33 * r34) + (l34 * r44);
|
||
e[outOffset + 12] = (l41 * r11) + (l42 * r21) + (l43 * r31) + (l44 * r41);
|
||
e[outOffset + 13] = (l41 * r12) + (l42 * r22) + (l43 * r32) + (l44 * r42);
|
||
e[outOffset + 14] = (l41 * r13) + (l42 * r23) + (l43 * r33) + (l44 * r43);
|
||
e[outOffset + 15] = (l41 * r14) + (l42 * r24) + (l43 * r34) + (l44 * r44);
|
||
}
|
||
static arcTanAngle(x, y) {
|
||
if (x == 0) {
|
||
if (y == 1)
|
||
return Math.PI / 2;
|
||
return -Math.PI / 2;
|
||
}
|
||
if (x > 0)
|
||
return Math.atan(y / x);
|
||
if (x < 0) {
|
||
if (y > 0)
|
||
return Math.atan(y / x) + Math.PI;
|
||
return Math.atan(y / x) - Math.PI;
|
||
}
|
||
return 0;
|
||
}
|
||
static angleTo(from, location, angle) {
|
||
Vector3.subtract(location, from, Quaternion.TEMPVector30);
|
||
Vector3.normalize(Quaternion.TEMPVector30, Quaternion.TEMPVector30);
|
||
angle.x = Math.asin(Quaternion.TEMPVector30.y);
|
||
angle.y = Utils3D.arcTanAngle(-Quaternion.TEMPVector30.z, -Quaternion.TEMPVector30.x);
|
||
}
|
||
static transformQuat(source, rotation, out) {
|
||
var re = rotation;
|
||
var x = source.x, y = source.y, z = source.z, qx = re[0], qy = re[1], qz = re[2], qw = re[3], ix = qw * x + qy * z - qz * y, iy = qw * y + qz * x - qx * z, iz = qw * z + qx * y - qy * x, iw = -qx * x - qy * y - qz * z;
|
||
out.x = ix * qw + iw * -qx + iy * -qz - iz * -qy;
|
||
out.y = iy * qw + iw * -qy + iz * -qx - ix * -qz;
|
||
out.z = iz * qw + iw * -qz + ix * -qy - iy * -qx;
|
||
}
|
||
static quaternionWeight(f, weight, e) {
|
||
e.x = f.x * weight;
|
||
e.y = f.y * weight;
|
||
e.z = f.z * weight;
|
||
e.w = f.w;
|
||
}
|
||
static quaternionConjugate(value, result) {
|
||
result.x = -value.x;
|
||
result.y = -value.y;
|
||
result.z = -value.z;
|
||
result.w = value.w;
|
||
}
|
||
static scaleWeight(s, w, out) {
|
||
var sX = s.x, sY = s.y, sZ = s.z;
|
||
out.x = sX > 0 ? Math.pow(Math.abs(sX), w) : -Math.pow(Math.abs(sX), w);
|
||
out.y = sY > 0 ? Math.pow(Math.abs(sY), w) : -Math.pow(Math.abs(sY), w);
|
||
out.z = sZ > 0 ? Math.pow(Math.abs(sZ), w) : -Math.pow(Math.abs(sZ), w);
|
||
}
|
||
static scaleBlend(sa, sb, w, out) {
|
||
var saw = Utils3D._tempVector3_0;
|
||
var sbw = Utils3D._tempVector3_1;
|
||
Utils3D.scaleWeight(sa, 1.0 - w, saw);
|
||
Utils3D.scaleWeight(sb, w, sbw);
|
||
var sng = w > 0.5 ? sb : sa;
|
||
out.x = sng.x > 0 ? Math.abs(saw.x * sbw.x) : -Math.abs(saw.x * sbw.x);
|
||
out.y = sng.y > 0 ? Math.abs(saw.y * sbw.y) : -Math.abs(saw.y * sbw.y);
|
||
out.z = sng.z > 0 ? Math.abs(saw.z * sbw.z) : -Math.abs(saw.z * sbw.z);
|
||
}
|
||
static matrix4x4MultiplyFFF(a, b, e) {
|
||
var i, ai0, ai1, ai2, ai3;
|
||
if (e === b) {
|
||
b = new Float32Array(16);
|
||
for (i = 0; i < 16; ++i) {
|
||
b[i] = e[i];
|
||
}
|
||
}
|
||
var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
|
||
var b4 = b[4], b5 = b[5], b6 = b[6], b7 = b[7];
|
||
var b8 = b[8], b9 = b[9], b10 = b[10], b11 = b[11];
|
||
var b12 = b[12], b13 = b[13], b14 = b[14], b15 = b[15];
|
||
for (i = 0; i < 4; i++) {
|
||
ai0 = a[i];
|
||
ai1 = a[i + 4];
|
||
ai2 = a[i + 8];
|
||
ai3 = a[i + 12];
|
||
e[i] = ai0 * b0 + ai1 * b1 + ai2 * b2 + ai3 * b3;
|
||
e[i + 4] = ai0 * b4 + ai1 * b5 + ai2 * b6 + ai3 * b7;
|
||
e[i + 8] = ai0 * b8 + ai1 * b9 + ai2 * b10 + ai3 * b11;
|
||
e[i + 12] = ai0 * b12 + ai1 * b13 + ai2 * b14 + ai3 * b15;
|
||
}
|
||
}
|
||
static matrix4x4MultiplyFFFForNative(a, b, e) {
|
||
Laya.LayaGL.instance.matrix4x4Multiply(a, b, e);
|
||
}
|
||
static matrix4x4MultiplyMFM(left, right, out) {
|
||
Utils3D.matrix4x4MultiplyFFF(left.elements, right, out.elements);
|
||
}
|
||
static _buildTexture2D(width, height, format, colorFunc, mipmaps = false) {
|
||
var texture = new Laya.Texture2D(width, height, format, mipmaps, true);
|
||
texture.anisoLevel = 1;
|
||
texture.filterMode = Laya.FilterMode.Point;
|
||
TextureGenerator._generateTexture2D(texture, width, height, colorFunc);
|
||
return texture;
|
||
}
|
||
static _drawBound(debugLine, boundBox, color) {
|
||
if (debugLine.lineCount + 12 > debugLine.maxLineCount)
|
||
debugLine.maxLineCount += 12;
|
||
var start = Utils3D._tempVector3_0;
|
||
var end = Utils3D._tempVector3_1;
|
||
var min = boundBox.min;
|
||
var max = boundBox.max;
|
||
start.setValue(min.x, min.y, min.z);
|
||
end.setValue(max.x, min.y, min.z);
|
||
debugLine.addLine(start, end, color, color);
|
||
start.setValue(min.x, min.y, min.z);
|
||
end.setValue(min.x, min.y, max.z);
|
||
debugLine.addLine(start, end, color, color);
|
||
start.setValue(max.x, min.y, min.z);
|
||
end.setValue(max.x, min.y, max.z);
|
||
debugLine.addLine(start, end, color, color);
|
||
start.setValue(min.x, min.y, max.z);
|
||
end.setValue(max.x, min.y, max.z);
|
||
debugLine.addLine(start, end, color, color);
|
||
start.setValue(min.x, min.y, min.z);
|
||
end.setValue(min.x, max.y, min.z);
|
||
debugLine.addLine(start, end, color, color);
|
||
start.setValue(min.x, min.y, max.z);
|
||
end.setValue(min.x, max.y, max.z);
|
||
debugLine.addLine(start, end, color, color);
|
||
start.setValue(max.x, min.y, min.z);
|
||
end.setValue(max.x, max.y, min.z);
|
||
debugLine.addLine(start, end, color, color);
|
||
start.setValue(max.x, min.y, max.z);
|
||
end.setValue(max.x, max.y, max.z);
|
||
debugLine.addLine(start, end, color, color);
|
||
start.setValue(min.x, max.y, min.z);
|
||
end.setValue(max.x, max.y, min.z);
|
||
debugLine.addLine(start, end, color, color);
|
||
start.setValue(min.x, max.y, min.z);
|
||
end.setValue(min.x, max.y, max.z);
|
||
debugLine.addLine(start, end, color, color);
|
||
start.setValue(max.x, max.y, min.z);
|
||
end.setValue(max.x, max.y, max.z);
|
||
debugLine.addLine(start, end, color, color);
|
||
start.setValue(min.x, max.y, max.z);
|
||
end.setValue(max.x, max.y, max.z);
|
||
debugLine.addLine(start, end, color, color);
|
||
}
|
||
static _getHierarchyPath(rootSprite, checkSprite, path) {
|
||
path.length = 0;
|
||
var sprite = checkSprite;
|
||
while (sprite !== rootSprite) {
|
||
var parent = sprite._parent;
|
||
if (parent)
|
||
path.push(parent.getChildIndex(sprite));
|
||
else
|
||
return null;
|
||
sprite = parent;
|
||
}
|
||
return path;
|
||
}
|
||
static _getNodeByHierarchyPath(rootSprite, invPath) {
|
||
var sprite = rootSprite;
|
||
for (var i = invPath.length - 1; i >= 0; i--) {
|
||
sprite = sprite.getChildAt(invPath[i]);
|
||
}
|
||
return sprite;
|
||
}
|
||
static uint8ArrayToArrayBuffer(rendertexture) {
|
||
let pixelArray;
|
||
let width = rendertexture.width;
|
||
let height = rendertexture.height;
|
||
switch (rendertexture.format) {
|
||
case Laya.RenderTextureFormat.R8G8B8:
|
||
pixelArray = new Uint8Array(width * height * 4);
|
||
break;
|
||
case Laya.RenderTextureFormat.R8G8B8A8:
|
||
pixelArray = new Uint8Array(width * height * 4);
|
||
break;
|
||
case Laya.RenderTextureFormat.R16G16B16A16:
|
||
pixelArray = new Float32Array(width * height * 4);
|
||
break;
|
||
default:
|
||
throw "this function is not surpprt " + rendertexture.format.toString() + "format Material";
|
||
}
|
||
rendertexture.getData(0, 0, rendertexture.width, rendertexture.height, pixelArray);
|
||
switch (rendertexture.format) {
|
||
case Laya.RenderTextureFormat.R16G16B16A16:
|
||
let ori = pixelArray;
|
||
let trans = new Uint8Array(width * height * 4);
|
||
for (let i = 0, n = ori.length; i < n; i++) {
|
||
trans[i] = Math.min(Math.floor(ori[i] * 255), 255);
|
||
}
|
||
pixelArray = trans;
|
||
break;
|
||
}
|
||
let pixels = pixelArray;
|
||
var bs;
|
||
if (Laya.Render.isConchApp) ;
|
||
else {
|
||
var canv = new Laya.HTMLCanvas(true);
|
||
canv.lock = true;
|
||
canv.size(width, height);
|
||
var ctx2d = canv.getContext('2d');
|
||
var imgdata = ctx2d.createImageData(width, height);
|
||
imgdata.data.set(new Uint8ClampedArray(pixels));
|
||
ctx2d.putImageData(imgdata, 0, 0);
|
||
bs = canv.source.toDataURL();
|
||
canv.destroy();
|
||
}
|
||
return bs;
|
||
}
|
||
}
|
||
Utils3D._tempVector3_0 = new Vector3();
|
||
Utils3D._tempVector3_1 = new Vector3();
|
||
Utils3D._tempArray16_0 = new Float32Array(16);
|
||
Utils3D._tempArray16_1 = new Float32Array(16);
|
||
Utils3D._tempArray16_2 = new Float32Array(16);
|
||
Utils3D._tempArray16_3 = new Float32Array(16);
|
||
Utils3D._compIdToNode = new Object();
|
||
|
||
class AnimationClip extends Laya.Resource {
|
||
constructor() {
|
||
super();
|
||
this._duration = 0;
|
||
this._frameRate = 0;
|
||
this._nodes = new KeyframeNodeList();
|
||
this.islooping = false;
|
||
this._animationEvents = [];
|
||
}
|
||
static _parse(data) {
|
||
var clip = new AnimationClip();
|
||
var reader = new Laya.Byte(data);
|
||
var version = reader.readUTFString();
|
||
switch (version) {
|
||
case "LAYAANIMATION:03":
|
||
AnimationClipParser03.parse(clip, reader);
|
||
break;
|
||
case "LAYAANIMATION:04":
|
||
case "LAYAANIMATION:COMPRESSION_04":
|
||
AnimationClipParser04.parse(clip, reader, version);
|
||
break;
|
||
default:
|
||
throw "unknown animationClip version.";
|
||
}
|
||
return clip;
|
||
}
|
||
static load(url, complete) {
|
||
Laya.ILaya.loader.create(url, complete, null, AnimationClip.ANIMATIONCLIP);
|
||
}
|
||
duration() {
|
||
return this._duration;
|
||
}
|
||
_hermiteInterpolate(frame, nextFrame, t, dur) {
|
||
var t0 = frame.outTangent, t1 = nextFrame.inTangent;
|
||
if (Number.isFinite(t0) && Number.isFinite(t1)) {
|
||
var t2 = t * t;
|
||
var t3 = t2 * t;
|
||
var a = 2.0 * t3 - 3.0 * t2 + 1.0;
|
||
var b = t3 - 2.0 * t2 + t;
|
||
var c = t3 - t2;
|
||
var d = -2.0 * t3 + 3.0 * t2;
|
||
return a * frame.value + b * t0 * dur + c * t1 * dur + d * nextFrame.value;
|
||
}
|
||
else
|
||
return frame.value;
|
||
}
|
||
_hermiteInterpolateVector3(frame, nextFrame, t, dur, out) {
|
||
var p0 = frame.value;
|
||
var tan0 = frame.outTangent;
|
||
var p1 = nextFrame.value;
|
||
var tan1 = nextFrame.inTangent;
|
||
var t2 = t * t;
|
||
var t3 = t2 * t;
|
||
var a = 2.0 * t3 - 3.0 * t2 + 1.0;
|
||
var b = t3 - 2.0 * t2 + t;
|
||
var c = t3 - t2;
|
||
var d = -2.0 * t3 + 3.0 * t2;
|
||
var t0 = tan0.x, t1 = tan1.x;
|
||
if (Number.isFinite(t0) && Number.isFinite(t1))
|
||
out.x = a * p0.x + b * t0 * dur + c * t1 * dur + d * p1.x;
|
||
else
|
||
out.x = p0.x;
|
||
t0 = tan0.y, t1 = tan1.y;
|
||
if (Number.isFinite(t0) && Number.isFinite(t1))
|
||
out.y = a * p0.y + b * t0 * dur + c * t1 * dur + d * p1.y;
|
||
else
|
||
out.y = p0.y;
|
||
t0 = tan0.z, t1 = tan1.z;
|
||
if (Number.isFinite(t0) && Number.isFinite(t1))
|
||
out.z = a * p0.z + b * t0 * dur + c * t1 * dur + d * p1.z;
|
||
else
|
||
out.z = p0.z;
|
||
}
|
||
_hermiteInterpolateQuaternion(frame, nextFrame, t, dur, out) {
|
||
var p0 = frame.value;
|
||
var tan0 = frame.outTangent;
|
||
var p1 = nextFrame.value;
|
||
var tan1 = nextFrame.inTangent;
|
||
var t2 = t * t;
|
||
var t3 = t2 * t;
|
||
var a = 2.0 * t3 - 3.0 * t2 + 1.0;
|
||
var b = t3 - 2.0 * t2 + t;
|
||
var c = t3 - t2;
|
||
var d = -2.0 * t3 + 3.0 * t2;
|
||
var t0 = tan0.x, t1 = tan1.x;
|
||
if (Number.isFinite(t0) && Number.isFinite(t1))
|
||
out.x = a * p0.x + b * t0 * dur + c * t1 * dur + d * p1.x;
|
||
else
|
||
out.x = p0.x;
|
||
t0 = tan0.y, t1 = tan1.y;
|
||
if (Number.isFinite(t0) && Number.isFinite(t1))
|
||
out.y = a * p0.y + b * t0 * dur + c * t1 * dur + d * p1.y;
|
||
else
|
||
out.y = p0.y;
|
||
t0 = tan0.z, t1 = tan1.z;
|
||
if (Number.isFinite(t0) && Number.isFinite(t1))
|
||
out.z = a * p0.z + b * t0 * dur + c * t1 * dur + d * p1.z;
|
||
else
|
||
out.z = p0.z;
|
||
t0 = tan0.w, t1 = tan1.w;
|
||
if (Number.isFinite(t0) && Number.isFinite(t1))
|
||
out.w = a * p0.w + b * t0 * dur + c * t1 * dur + d * p1.w;
|
||
else
|
||
out.w = p0.w;
|
||
}
|
||
_evaluateClipDatasRealTime(nodes, playCurTime, realTimeCurrentFrameIndexes, addtive, frontPlay, outDatas, avatarMask) {
|
||
for (var i = 0, n = nodes.count; i < n; i++) {
|
||
var node = nodes.getNodeByIndex(i);
|
||
var type = node.type;
|
||
var nextFrameIndex;
|
||
var keyFrames = node._keyFrames;
|
||
var keyFramesCount = keyFrames.length;
|
||
var frameIndex = realTimeCurrentFrameIndexes[i];
|
||
if (avatarMask && (!avatarMask.getTransformActive(node.nodePath))) {
|
||
continue;
|
||
}
|
||
if (frontPlay) {
|
||
if ((frameIndex !== -1) && (playCurTime < keyFrames[frameIndex].time)) {
|
||
frameIndex = -1;
|
||
realTimeCurrentFrameIndexes[i] = frameIndex;
|
||
}
|
||
nextFrameIndex = frameIndex + 1;
|
||
while (nextFrameIndex < keyFramesCount) {
|
||
if (keyFrames[nextFrameIndex].time > playCurTime)
|
||
break;
|
||
frameIndex++;
|
||
nextFrameIndex++;
|
||
realTimeCurrentFrameIndexes[i] = frameIndex;
|
||
}
|
||
}
|
||
else {
|
||
nextFrameIndex = frameIndex + 1;
|
||
if ((nextFrameIndex !== keyFramesCount) && (playCurTime > keyFrames[nextFrameIndex].time)) {
|
||
frameIndex = keyFramesCount - 1;
|
||
realTimeCurrentFrameIndexes[i] = frameIndex;
|
||
}
|
||
nextFrameIndex = frameIndex + 1;
|
||
while (frameIndex > -1) {
|
||
if (keyFrames[frameIndex].time < playCurTime)
|
||
break;
|
||
frameIndex--;
|
||
nextFrameIndex--;
|
||
realTimeCurrentFrameIndexes[i] = frameIndex;
|
||
}
|
||
}
|
||
var isEnd = nextFrameIndex === keyFramesCount;
|
||
switch (type) {
|
||
case 0:
|
||
if (frameIndex !== -1) {
|
||
var frame = keyFrames[frameIndex];
|
||
if (isEnd) {
|
||
outDatas[i] = frame.value;
|
||
}
|
||
else {
|
||
var nextFarme = keyFrames[nextFrameIndex];
|
||
var d = nextFarme.time - frame.time;
|
||
var t;
|
||
if (d !== 0)
|
||
t = (playCurTime - frame.time) / d;
|
||
else
|
||
t = 0;
|
||
outDatas[i] = this._hermiteInterpolate(frame, nextFarme, t, d);
|
||
}
|
||
}
|
||
else {
|
||
outDatas[i] = keyFrames[0].value;
|
||
}
|
||
if (addtive)
|
||
outDatas[i] = outDatas[i] - keyFrames[0].value;
|
||
break;
|
||
case 1:
|
||
case 4:
|
||
var clipData = outDatas[i];
|
||
this._evaluateFrameNodeVector3DatasRealTime(keyFrames, frameIndex, isEnd, playCurTime, clipData);
|
||
if (addtive) {
|
||
var firstFrameValue = keyFrames[0].value;
|
||
clipData.x -= firstFrameValue.x;
|
||
clipData.y -= firstFrameValue.y;
|
||
clipData.z -= firstFrameValue.z;
|
||
}
|
||
break;
|
||
case 2:
|
||
var clipQuat = outDatas[i];
|
||
this._evaluateFrameNodeQuaternionDatasRealTime(keyFrames, frameIndex, isEnd, playCurTime, clipQuat);
|
||
if (addtive) {
|
||
var tempQuat = AnimationClip._tempQuaternion0;
|
||
var firstFrameValueQua = keyFrames[0].value;
|
||
Utils3D.quaternionConjugate(firstFrameValueQua, tempQuat);
|
||
Quaternion.multiply(tempQuat, clipQuat, clipQuat);
|
||
}
|
||
break;
|
||
case 3:
|
||
clipData = outDatas[i];
|
||
this._evaluateFrameNodeVector3DatasRealTime(keyFrames, frameIndex, isEnd, playCurTime, clipData);
|
||
if (addtive) {
|
||
firstFrameValue = keyFrames[0].value;
|
||
clipData.x /= firstFrameValue.x;
|
||
clipData.y /= firstFrameValue.y;
|
||
clipData.z /= firstFrameValue.z;
|
||
}
|
||
break;
|
||
default:
|
||
throw "AnimationClip:unknown node type.";
|
||
}
|
||
}
|
||
}
|
||
_evaluateClipDatasRealTimeForNative(nodes, playCurTime, realTimeCurrentFrameIndexes, addtive) {
|
||
Laya.LayaGL.instance.evaluateClipDatasRealTime(nodes._nativeObj, playCurTime, realTimeCurrentFrameIndexes, addtive);
|
||
}
|
||
_evaluateFrameNodeVector3DatasRealTime(keyFrames, frameIndex, isEnd, playCurTime, outDatas) {
|
||
if (frameIndex !== -1) {
|
||
var frame = keyFrames[frameIndex];
|
||
if (isEnd) {
|
||
var frameData = frame.value;
|
||
outDatas.x = frameData.x;
|
||
outDatas.y = frameData.y;
|
||
outDatas.z = frameData.z;
|
||
}
|
||
else {
|
||
var nextKeyFrame = keyFrames[frameIndex + 1];
|
||
var t;
|
||
var startTime = frame.time;
|
||
var d = nextKeyFrame.time - startTime;
|
||
if (d !== 0)
|
||
t = (playCurTime - startTime) / d;
|
||
else
|
||
t = 0;
|
||
this._hermiteInterpolateVector3(frame, nextKeyFrame, t, d, outDatas);
|
||
}
|
||
}
|
||
else {
|
||
var firstFrameDatas = keyFrames[0].value;
|
||
outDatas.x = firstFrameDatas.x;
|
||
outDatas.y = firstFrameDatas.y;
|
||
outDatas.z = firstFrameDatas.z;
|
||
}
|
||
}
|
||
_evaluateFrameNodeQuaternionDatasRealTime(keyFrames, frameIndex, isEnd, playCurTime, outDatas) {
|
||
if (frameIndex !== -1) {
|
||
var frame = keyFrames[frameIndex];
|
||
if (isEnd) {
|
||
var frameData = frame.value;
|
||
outDatas.x = frameData.x;
|
||
outDatas.y = frameData.y;
|
||
outDatas.z = frameData.z;
|
||
outDatas.w = frameData.w;
|
||
}
|
||
else {
|
||
var nextKeyFrame = keyFrames[frameIndex + 1];
|
||
var t;
|
||
var startTime = frame.time;
|
||
var d = nextKeyFrame.time - startTime;
|
||
if (d !== 0)
|
||
t = (playCurTime - startTime) / d;
|
||
else
|
||
t = 0;
|
||
this._hermiteInterpolateQuaternion(frame, nextKeyFrame, t, d, outDatas);
|
||
}
|
||
}
|
||
else {
|
||
var firstFrameDatas = keyFrames[0].value;
|
||
outDatas.x = firstFrameDatas.x;
|
||
outDatas.y = firstFrameDatas.y;
|
||
outDatas.z = firstFrameDatas.z;
|
||
outDatas.w = firstFrameDatas.w;
|
||
}
|
||
}
|
||
_binarySearchEventIndex(time) {
|
||
var start = 0;
|
||
var end = this._animationEvents.length - 1;
|
||
var mid;
|
||
while (start <= end) {
|
||
mid = Math.floor((start + end) / 2);
|
||
var midValue = this._animationEvents[mid].time;
|
||
if (midValue == time)
|
||
return mid;
|
||
else if (midValue > time)
|
||
end = mid - 1;
|
||
else
|
||
start = mid + 1;
|
||
}
|
||
return start;
|
||
}
|
||
addEvent(event) {
|
||
var index = this._binarySearchEventIndex(event.time);
|
||
this._animationEvents.splice(index, 0, event);
|
||
}
|
||
_disposeResource() {
|
||
this._nodes = null;
|
||
this._nodesMap = null;
|
||
}
|
||
}
|
||
AnimationClip.ANIMATIONCLIP = "ANIMATIONCLIP";
|
||
AnimationClip._tempQuaternion0 = new Quaternion();
|
||
|
||
class AnimatorPlayState {
|
||
constructor() {
|
||
this._currentState = null;
|
||
}
|
||
get normalizedTime() {
|
||
return this._normalizedTime;
|
||
}
|
||
get duration() {
|
||
return this._duration;
|
||
}
|
||
get animatorState() {
|
||
return this._currentState;
|
||
}
|
||
_resetPlayState(startTime, clipDuration) {
|
||
this._finish = false;
|
||
this._startPlayTime = startTime;
|
||
this._elapsedTime = startTime;
|
||
this._playEventIndex = 0;
|
||
this._lastIsFront = true;
|
||
this._normalizedTime = this._elapsedTime / clipDuration;
|
||
var playTime = this._normalizedTime % 1.0;
|
||
this._normalizedPlayTime = playTime < 0 ? playTime + 1.0 : playTime;
|
||
}
|
||
_cloneTo(dest) {
|
||
dest._finish = this._finish;
|
||
dest._startPlayTime = this._startPlayTime;
|
||
dest._elapsedTime = this._elapsedTime;
|
||
dest._normalizedTime = this._normalizedTime;
|
||
dest._normalizedPlayTime = this._normalizedPlayTime;
|
||
dest._playEventIndex = this._playEventIndex;
|
||
dest._lastIsFront = this._lastIsFront;
|
||
}
|
||
}
|
||
|
||
class AnimatorControllerLayer {
|
||
constructor(name) {
|
||
this._referenceCount = 0;
|
||
this._playType = -1;
|
||
this._crossDuration = -1;
|
||
this._crossMark = 0;
|
||
this._crossNodesOwnersCount = 0;
|
||
this._crossNodesOwners = [];
|
||
this._crossNodesOwnersIndicesMap = {};
|
||
this._srcCrossClipNodeIndices = [];
|
||
this._destCrossClipNodeIndices = [];
|
||
this._statesMap = {};
|
||
this._states = [];
|
||
this._playStateInfo = new AnimatorPlayState();
|
||
this._crossPlayStateInfo = new AnimatorPlayState();
|
||
this.blendingMode = AnimatorControllerLayer.BLENDINGMODE_OVERRIDE;
|
||
this.defaultWeight = 1.0;
|
||
this.playOnWake = true;
|
||
this.name = name;
|
||
}
|
||
get defaultState() {
|
||
return this._defaultState;
|
||
}
|
||
set defaultState(value) {
|
||
this._defaultState = value;
|
||
this._statesMap[value.name] = value;
|
||
}
|
||
get avatarMask() {
|
||
return this._avatarMask;
|
||
}
|
||
set avatarMask(value) {
|
||
this._avatarMask = value;
|
||
}
|
||
_removeClip(clipStateInfos, statesMap, index, state) {
|
||
var clip = state._clip;
|
||
var clipStateInfo = clipStateInfos[index];
|
||
clipStateInfos.splice(index, 1);
|
||
delete statesMap[state.name];
|
||
if (this._animator) {
|
||
var frameNodes = clip._nodes;
|
||
var nodeOwners = clipStateInfo._nodeOwners;
|
||
clip._removeReference();
|
||
for (var i = 0, n = frameNodes.count; i < n; i++)
|
||
this._animator._removeKeyframeNodeOwner(nodeOwners, frameNodes.getNodeByIndex(i));
|
||
}
|
||
}
|
||
_getReferenceCount() {
|
||
return this._referenceCount;
|
||
}
|
||
_addReference(count = 1) {
|
||
for (var i = 0, n = this._states.length; i < n; i++)
|
||
this._states[i]._addReference(count);
|
||
this._referenceCount += count;
|
||
}
|
||
_removeReference(count = 1) {
|
||
for (var i = 0, n = this._states.length; i < n; i++)
|
||
this._states[i]._removeReference(count);
|
||
this._referenceCount -= count;
|
||
}
|
||
_clearReference() {
|
||
this._removeReference(-this._referenceCount);
|
||
}
|
||
getCurrentPlayState() {
|
||
return this._playStateInfo;
|
||
}
|
||
getAnimatorState(name) {
|
||
var state = this._statesMap[name];
|
||
return state ? state : null;
|
||
}
|
||
addState(state) {
|
||
var stateName = state.name;
|
||
if (this._statesMap[stateName]) {
|
||
throw "AnimatorControllerLayer:this stat's name has exist.";
|
||
}
|
||
else {
|
||
this._statesMap[stateName] = state;
|
||
this._states.push(state);
|
||
if (this._animator) {
|
||
state._clip._addReference();
|
||
this._animator._getOwnersByClip(state);
|
||
}
|
||
}
|
||
}
|
||
removeState(state) {
|
||
var states = this._states;
|
||
var index = -1;
|
||
for (var i = 0, n = states.length; i < n; i++) {
|
||
if (states[i] === state) {
|
||
index = i;
|
||
break;
|
||
}
|
||
}
|
||
if (index !== -1)
|
||
this._removeClip(states, this._statesMap, index, state);
|
||
}
|
||
destroy() {
|
||
this._clearReference();
|
||
this._statesMap = null;
|
||
this._states = [];
|
||
this._playStateInfo = null;
|
||
this._crossPlayStateInfo = null;
|
||
this._defaultState = null;
|
||
}
|
||
cloneTo(destObject) {
|
||
var dest = destObject;
|
||
dest.name = this.name;
|
||
dest.blendingMode = this.blendingMode;
|
||
dest.defaultWeight = this.defaultWeight;
|
||
dest.playOnWake = this.playOnWake;
|
||
}
|
||
clone() {
|
||
var dest = new AnimatorControllerLayer(this.name);
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
}
|
||
AnimatorControllerLayer.BLENDINGMODE_OVERRIDE = 0;
|
||
AnimatorControllerLayer.BLENDINGMODE_ADDTIVE = 1;
|
||
|
||
class AnimatorState {
|
||
constructor() {
|
||
this._referenceCount = 0;
|
||
this._clip = null;
|
||
this._nodeOwners = [];
|
||
this._currentFrameIndices = null;
|
||
this._realtimeDatas = [];
|
||
this._scripts = null;
|
||
this.speed = 1.0;
|
||
this.clipStart = 0.0;
|
||
this.clipEnd = 1.0;
|
||
}
|
||
get clip() {
|
||
return this._clip;
|
||
}
|
||
set clip(value) {
|
||
if (this._clip !== value) {
|
||
if (this._clip)
|
||
(this._referenceCount > 0) && (this._clip._removeReference(this._referenceCount));
|
||
if (value) {
|
||
var realtimeDatas = this._realtimeDatas;
|
||
var clipNodes = value._nodes;
|
||
var count = clipNodes.count;
|
||
this._currentFrameIndices = new Int16Array(count);
|
||
this._resetFrameIndices();
|
||
(this._referenceCount > 0) && (value._addReference(this._referenceCount));
|
||
this._realtimeDatas.length = count;
|
||
for (var i = 0; i < count; i++) {
|
||
switch (clipNodes.getNodeByIndex(i).type) {
|
||
case 0:
|
||
break;
|
||
case 1:
|
||
case 3:
|
||
case 4:
|
||
realtimeDatas[i] = new Vector3();
|
||
break;
|
||
case 2:
|
||
realtimeDatas[i] = new Quaternion();
|
||
break;
|
||
default:
|
||
throw "AnimationClipParser04:unknown type.";
|
||
}
|
||
}
|
||
}
|
||
this._clip = value;
|
||
}
|
||
}
|
||
_getReferenceCount() {
|
||
return this._referenceCount;
|
||
}
|
||
_addReference(count = 1) {
|
||
(this._clip) && (this._clip._addReference(count));
|
||
this._referenceCount += count;
|
||
}
|
||
_removeReference(count = 1) {
|
||
(this._clip) && (this._clip._removeReference(count));
|
||
this._referenceCount -= count;
|
||
}
|
||
_clearReference() {
|
||
this._removeReference(-this._referenceCount);
|
||
}
|
||
_resetFrameIndices() {
|
||
for (var i = 0, n = this._currentFrameIndices.length; i < n; i++)
|
||
this._currentFrameIndices[i] = -1;
|
||
}
|
||
addScript(type) {
|
||
var script = new type();
|
||
this._scripts = this._scripts || [];
|
||
this._scripts.push(script);
|
||
return script;
|
||
}
|
||
getScript(type) {
|
||
if (this._scripts) {
|
||
for (var i = 0, n = this._scripts.length; i < n; i++) {
|
||
var script = this._scripts[i];
|
||
if (script instanceof type)
|
||
return script;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
getScripts(type) {
|
||
var coms = null;
|
||
if (this._scripts) {
|
||
for (var i = 0, n = this._scripts.length; i < n; i++) {
|
||
var script = this._scripts[i];
|
||
if (script instanceof type) {
|
||
coms = coms || [];
|
||
coms.push(script);
|
||
}
|
||
}
|
||
}
|
||
return coms;
|
||
}
|
||
cloneTo(destObject) {
|
||
var dest = destObject;
|
||
dest.name = this.name;
|
||
dest.speed = this.speed;
|
||
dest.clipStart = this.clipStart;
|
||
dest.clipEnd = this.clipEnd;
|
||
dest.clip = this._clip;
|
||
}
|
||
clone() {
|
||
var dest = new AnimatorState();
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
}
|
||
|
||
class AvatarMask {
|
||
constructor(animator) {
|
||
this._avatarPathMap = {};
|
||
this._catchAnimator = animator;
|
||
}
|
||
get getCatchAnimator() {
|
||
return this._catchAnimator;
|
||
}
|
||
getTransformActive(path) {
|
||
return this._avatarPathMap[path];
|
||
}
|
||
setTransformActive(path, value) {
|
||
this._avatarPathMap[path] = value;
|
||
}
|
||
getAllTranfromPath() {
|
||
return this._avatarPathMap;
|
||
}
|
||
}
|
||
|
||
class KeyframeNodeOwner {
|
||
constructor() {
|
||
this.indexInList = -1;
|
||
this.referenceCount = 0;
|
||
this.updateMark = -1;
|
||
this.type = -1;
|
||
this.fullPath = null;
|
||
this.propertyOwner = null;
|
||
this.property = null;
|
||
this.defaultValue = null;
|
||
this.value = null;
|
||
this.crossFixedValue = null;
|
||
}
|
||
saveCrossFixedValue() {
|
||
var pro = this.propertyOwner;
|
||
if (pro) {
|
||
switch (this.type) {
|
||
case 0:
|
||
this.crossFixedValue = this.value;
|
||
break;
|
||
case 1:
|
||
case 3:
|
||
case 4:
|
||
this.value.cloneTo(this.crossFixedValue);
|
||
break;
|
||
case 2:
|
||
this.value.cloneTo(this.crossFixedValue);
|
||
break;
|
||
default:
|
||
throw "Animator:unknown type.";
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
class Animator extends Laya.Component {
|
||
constructor() {
|
||
super();
|
||
this._keyframeNodeOwners = [];
|
||
this._linkAvatarSpritesData = {};
|
||
this._linkAvatarSprites = [];
|
||
this._renderableSprites = [];
|
||
this.cullingMode = Animator.CULLINGMODE_CULLCOMPLETELY;
|
||
this._controllerLayers = [];
|
||
this._linkSprites = {};
|
||
this._speed = 1.0;
|
||
this._keyframeNodeOwnerMap = {};
|
||
this._updateMark = 0;
|
||
}
|
||
static _update(scene) {
|
||
var pool = scene._animatorPool;
|
||
var elements = pool.elements;
|
||
for (var i = 0, n = pool.length; i < n; i++) {
|
||
var animator = elements[i];
|
||
(animator && animator.enabled) && (animator._update());
|
||
}
|
||
}
|
||
get speed() {
|
||
return this._speed;
|
||
}
|
||
set speed(value) {
|
||
this._speed = value;
|
||
}
|
||
get controllerLayerCount() {
|
||
return this._controllerLayers.length;
|
||
}
|
||
_linkToSprites(linkSprites) {
|
||
for (var k in linkSprites) {
|
||
var nodeOwner = this.owner;
|
||
var path = linkSprites[k];
|
||
for (var j = 0, m = path.length; j < m; j++) {
|
||
var p = path[j];
|
||
if (p === "") {
|
||
break;
|
||
}
|
||
else {
|
||
nodeOwner = nodeOwner.getChildByName(p);
|
||
if (!nodeOwner)
|
||
break;
|
||
}
|
||
}
|
||
(nodeOwner) && (this.linkSprite3DToAvatarNode(k, nodeOwner));
|
||
}
|
||
}
|
||
_addKeyframeNodeOwner(clipOwners, node, propertyOwner) {
|
||
var nodeIndex = node._indexInList;
|
||
var fullPath = node.fullPath;
|
||
var keyframeNodeOwner = this._keyframeNodeOwnerMap[fullPath];
|
||
if (keyframeNodeOwner) {
|
||
keyframeNodeOwner.referenceCount++;
|
||
clipOwners[nodeIndex] = keyframeNodeOwner;
|
||
}
|
||
else {
|
||
var property = propertyOwner;
|
||
for (var i = 0, n = node.propertyCount; i < n; i++) {
|
||
property = property[node.getPropertyByIndex(i)];
|
||
if (!property)
|
||
break;
|
||
}
|
||
keyframeNodeOwner = this._keyframeNodeOwnerMap[fullPath] = new KeyframeNodeOwner();
|
||
keyframeNodeOwner.fullPath = fullPath;
|
||
keyframeNodeOwner.indexInList = this._keyframeNodeOwners.length;
|
||
keyframeNodeOwner.referenceCount = 1;
|
||
keyframeNodeOwner.propertyOwner = propertyOwner;
|
||
var propertyCount = node.propertyCount;
|
||
var propertys = [];
|
||
for (i = 0; i < propertyCount; i++)
|
||
propertys[i] = node.getPropertyByIndex(i);
|
||
keyframeNodeOwner.property = propertys;
|
||
keyframeNodeOwner.type = node.type;
|
||
if (property) {
|
||
if (node.type === 0) {
|
||
keyframeNodeOwner.defaultValue = property;
|
||
}
|
||
else {
|
||
var defaultValue = new property.constructor();
|
||
property.cloneTo(defaultValue);
|
||
keyframeNodeOwner.defaultValue = defaultValue;
|
||
keyframeNodeOwner.value = new property.constructor();
|
||
keyframeNodeOwner.crossFixedValue = new property.constructor();
|
||
}
|
||
}
|
||
this._keyframeNodeOwners.push(keyframeNodeOwner);
|
||
clipOwners[nodeIndex] = keyframeNodeOwner;
|
||
}
|
||
}
|
||
_removeKeyframeNodeOwner(nodeOwners, node) {
|
||
var fullPath = node.fullPath;
|
||
var keyframeNodeOwner = this._keyframeNodeOwnerMap[fullPath];
|
||
if (keyframeNodeOwner) {
|
||
keyframeNodeOwner.referenceCount--;
|
||
if (keyframeNodeOwner.referenceCount === 0) {
|
||
delete this._keyframeNodeOwnerMap[fullPath];
|
||
this._keyframeNodeOwners.splice(this._keyframeNodeOwners.indexOf(keyframeNodeOwner), 1);
|
||
}
|
||
nodeOwners[node._indexInList] = null;
|
||
}
|
||
}
|
||
_getOwnersByClip(clipStateInfo) {
|
||
var frameNodes = clipStateInfo._clip._nodes;
|
||
var frameNodesCount = frameNodes.count;
|
||
var nodeOwners = clipStateInfo._nodeOwners;
|
||
nodeOwners.length = frameNodesCount;
|
||
for (var i = 0; i < frameNodesCount; i++) {
|
||
var node = frameNodes.getNodeByIndex(i);
|
||
var property = this._avatar ? this._avatarNodeMap[this._avatar._rootNode.name] : this.owner;
|
||
for (var j = 0, m = node.ownerPathCount; j < m; j++) {
|
||
var ownPat = node.getOwnerPathByIndex(j);
|
||
if (ownPat === "") {
|
||
break;
|
||
}
|
||
else {
|
||
property = property.getChildByName(ownPat);
|
||
if (!property)
|
||
break;
|
||
}
|
||
}
|
||
if (property) {
|
||
var propertyOwner = node.propertyOwner;
|
||
(propertyOwner) && (property = property[propertyOwner]);
|
||
property && this._addKeyframeNodeOwner(nodeOwners, node, property);
|
||
}
|
||
}
|
||
}
|
||
_updatePlayer(animatorState, playState, elapsedTime, islooping) {
|
||
var clipDuration = animatorState._clip._duration * (animatorState.clipEnd - animatorState.clipStart);
|
||
var lastElapsedTime = playState._elapsedTime;
|
||
var elapsedPlaybackTime = lastElapsedTime + elapsedTime;
|
||
playState._lastElapsedTime = lastElapsedTime;
|
||
playState._elapsedTime = elapsedPlaybackTime;
|
||
var normalizedTime = elapsedPlaybackTime / clipDuration;
|
||
playState._normalizedTime = normalizedTime;
|
||
var playTime = normalizedTime % 1.0;
|
||
playState._normalizedPlayTime = playTime < 0 ? playTime + 1.0 : playTime;
|
||
playState._duration = clipDuration;
|
||
var scripts = animatorState._scripts;
|
||
if ((!islooping && elapsedPlaybackTime >= clipDuration)) {
|
||
playState._finish = true;
|
||
playState._elapsedTime = clipDuration;
|
||
playState._normalizedPlayTime = 1.0;
|
||
return;
|
||
}
|
||
if (scripts) {
|
||
for (var i = 0, n = scripts.length; i < n; i++)
|
||
scripts[i].onStateUpdate();
|
||
}
|
||
}
|
||
_updateStateFinish(animatorState, playState) {
|
||
if (playState._finish) {
|
||
var scripts = animatorState._scripts;
|
||
if (scripts) {
|
||
for (var i = 0, n = scripts.length; i < n; i++) {
|
||
scripts[i].onStateExit();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
_eventScript(scripts, events, eventIndex, endTime, front) {
|
||
if (front) {
|
||
for (var n = events.length; eventIndex < n; eventIndex++) {
|
||
var event = events[eventIndex];
|
||
if (event.time <= endTime) {
|
||
for (var j = 0, m = scripts.length; j < m; j++) {
|
||
var script = scripts[j];
|
||
var fun = script[event.eventName];
|
||
(fun) && (fun.apply(script, event.params));
|
||
}
|
||
}
|
||
else {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
for (; eventIndex >= 0; eventIndex--) {
|
||
event = events[eventIndex];
|
||
if (event.time >= endTime) {
|
||
for (j = 0, m = scripts.length; j < m; j++) {
|
||
script = scripts[j];
|
||
fun = script[event.eventName];
|
||
(fun) && (fun.apply(script, event.params));
|
||
}
|
||
}
|
||
else {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
return eventIndex;
|
||
}
|
||
_updateEventScript(stateInfo, playStateInfo) {
|
||
var scripts = this.owner._scripts;
|
||
if (scripts) {
|
||
var clip = stateInfo._clip;
|
||
var events = clip._animationEvents;
|
||
var clipDuration = clip._duration;
|
||
var elapsedTime = playStateInfo._elapsedTime;
|
||
var time = elapsedTime % clipDuration;
|
||
var loopCount = Math.abs(Math.floor(elapsedTime / clipDuration) - Math.floor(playStateInfo._lastElapsedTime / clipDuration));
|
||
var frontPlay = playStateInfo._elapsedTime >= playStateInfo._lastElapsedTime;
|
||
if (playStateInfo._lastIsFront !== frontPlay) {
|
||
if (frontPlay)
|
||
playStateInfo._playEventIndex++;
|
||
else
|
||
playStateInfo._playEventIndex--;
|
||
playStateInfo._lastIsFront = frontPlay;
|
||
}
|
||
var preEventIndex = playStateInfo._playEventIndex;
|
||
if (frontPlay) {
|
||
var newEventIndex = this._eventScript(scripts, events, playStateInfo._playEventIndex, loopCount > 0 ? clipDuration : time, true);
|
||
(preEventIndex === playStateInfo._playEventIndex) && (playStateInfo._playEventIndex = newEventIndex);
|
||
for (var i = 0, n = loopCount - 1; i < n; i++)
|
||
this._eventScript(scripts, events, 0, clipDuration, true);
|
||
(loopCount > 0 && time > 0) && (playStateInfo._playEventIndex = this._eventScript(scripts, events, 0, time, true));
|
||
}
|
||
else {
|
||
var newEventIndex = this._eventScript(scripts, events, playStateInfo._playEventIndex, loopCount > 0 ? 0 : time, false);
|
||
(preEventIndex === playStateInfo._playEventIndex) && (playStateInfo._playEventIndex = newEventIndex);
|
||
var eventIndex = events.length - 1;
|
||
for (i = 0, n = loopCount - 1; i < n; i++)
|
||
this._eventScript(scripts, events, eventIndex, 0, false);
|
||
(loopCount > 0 && time > 0) && (playStateInfo._playEventIndex = this._eventScript(scripts, events, eventIndex, time, false));
|
||
}
|
||
}
|
||
}
|
||
_updateClipDatas(animatorState, addtive, playStateInfo, animatorMask = null) {
|
||
var clip = animatorState._clip;
|
||
var clipDuration = clip._duration;
|
||
var curPlayTime = animatorState.clipStart * clipDuration + playStateInfo._normalizedPlayTime * playStateInfo._duration;
|
||
var currentFrameIndices = animatorState._currentFrameIndices;
|
||
var frontPlay = playStateInfo._elapsedTime > playStateInfo._lastElapsedTime;
|
||
clip._evaluateClipDatasRealTime(clip._nodes, curPlayTime, currentFrameIndices, addtive, frontPlay, animatorState._realtimeDatas, animatorMask);
|
||
}
|
||
_applyFloat(pro, proName, nodeOwner, additive, weight, isFirstLayer, data) {
|
||
if (nodeOwner.updateMark === this._updateMark) {
|
||
if (additive) {
|
||
pro[proName] += weight * data;
|
||
}
|
||
else {
|
||
var oriValue = pro[proName];
|
||
pro[proName] = oriValue + weight * (data - oriValue);
|
||
}
|
||
}
|
||
else {
|
||
if (isFirstLayer) {
|
||
if (additive)
|
||
pro[proName] = nodeOwner.defaultValue + data;
|
||
else
|
||
pro[proName] = data;
|
||
}
|
||
else {
|
||
if (additive) {
|
||
pro[proName] = nodeOwner.defaultValue + weight * (data);
|
||
}
|
||
else {
|
||
var defValue = nodeOwner.defaultValue;
|
||
pro[proName] = defValue + weight * (data - defValue);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
_applyPositionAndRotationEuler(nodeOwner, additive, weight, isFirstLayer, data, out) {
|
||
if (nodeOwner.updateMark === this._updateMark) {
|
||
if (additive) {
|
||
out.x += weight * data.x;
|
||
out.y += weight * data.y;
|
||
out.z += weight * data.z;
|
||
}
|
||
else {
|
||
var oriX = out.x;
|
||
var oriY = out.y;
|
||
var oriZ = out.z;
|
||
out.x = oriX + weight * (data.x - oriX);
|
||
out.y = oriY + weight * (data.y - oriY);
|
||
out.z = oriZ + weight * (data.z - oriZ);
|
||
}
|
||
}
|
||
else {
|
||
if (isFirstLayer) {
|
||
if (additive) {
|
||
var defValue = nodeOwner.defaultValue;
|
||
out.x = defValue.x + data.x;
|
||
out.y = defValue.y + data.y;
|
||
out.z = defValue.z + data.z;
|
||
}
|
||
else {
|
||
out.x = data.x;
|
||
out.y = data.y;
|
||
out.z = data.z;
|
||
}
|
||
}
|
||
else {
|
||
defValue = nodeOwner.defaultValue;
|
||
if (additive) {
|
||
out.x = defValue.x + weight * data.x;
|
||
out.y = defValue.y + weight * data.y;
|
||
out.z = defValue.z + weight * data.z;
|
||
}
|
||
else {
|
||
var defX = defValue.x;
|
||
var defY = defValue.y;
|
||
var defZ = defValue.z;
|
||
out.x = defX + weight * (data.x - defX);
|
||
out.y = defY + weight * (data.y - defY);
|
||
out.z = defZ + weight * (data.z - defZ);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
_applyRotation(nodeOwner, additive, weight, isFirstLayer, clipRot, localRotation) {
|
||
if (nodeOwner.updateMark === this._updateMark) {
|
||
if (additive) {
|
||
var tempQuat = Animator._tempQuaternion1;
|
||
Utils3D.quaternionWeight(clipRot, weight, tempQuat);
|
||
tempQuat.normalize(tempQuat);
|
||
Quaternion.multiply(localRotation, tempQuat, localRotation);
|
||
}
|
||
else {
|
||
Quaternion.lerp(localRotation, clipRot, weight, localRotation);
|
||
}
|
||
}
|
||
else {
|
||
if (isFirstLayer) {
|
||
if (additive) {
|
||
var defaultRot = nodeOwner.defaultValue;
|
||
Quaternion.multiply(defaultRot, clipRot, localRotation);
|
||
}
|
||
else {
|
||
localRotation.x = clipRot.x;
|
||
localRotation.y = clipRot.y;
|
||
localRotation.z = clipRot.z;
|
||
localRotation.w = clipRot.w;
|
||
}
|
||
}
|
||
else {
|
||
defaultRot = nodeOwner.defaultValue;
|
||
if (additive) {
|
||
tempQuat = Animator._tempQuaternion1;
|
||
Utils3D.quaternionWeight(clipRot, weight, tempQuat);
|
||
tempQuat.normalize(tempQuat);
|
||
Quaternion.multiply(defaultRot, tempQuat, localRotation);
|
||
}
|
||
else {
|
||
Quaternion.lerp(defaultRot, clipRot, weight, localRotation);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
_applyScale(nodeOwner, additive, weight, isFirstLayer, clipSca, localScale) {
|
||
if (nodeOwner.updateMark === this._updateMark) {
|
||
if (additive) {
|
||
var scale = Animator._tempVector31;
|
||
Utils3D.scaleWeight(clipSca, weight, scale);
|
||
localScale.x = localScale.x * scale.x;
|
||
localScale.y = localScale.y * scale.y;
|
||
localScale.z = localScale.z * scale.z;
|
||
}
|
||
else {
|
||
Utils3D.scaleBlend(localScale, clipSca, weight, localScale);
|
||
}
|
||
}
|
||
else {
|
||
if (isFirstLayer) {
|
||
if (additive) {
|
||
var defaultSca = nodeOwner.defaultValue;
|
||
localScale.x = defaultSca.x * clipSca.x;
|
||
localScale.y = defaultSca.y * clipSca.y;
|
||
localScale.z = defaultSca.z * clipSca.z;
|
||
}
|
||
else {
|
||
localScale.x = clipSca.x;
|
||
localScale.y = clipSca.y;
|
||
localScale.z = clipSca.z;
|
||
}
|
||
}
|
||
else {
|
||
defaultSca = nodeOwner.defaultValue;
|
||
if (additive) {
|
||
scale = Animator._tempVector31;
|
||
Utils3D.scaleWeight(clipSca, weight, scale);
|
||
localScale.x = defaultSca.x * scale.x;
|
||
localScale.y = defaultSca.y * scale.y;
|
||
localScale.z = defaultSca.z * scale.z;
|
||
}
|
||
else {
|
||
Utils3D.scaleBlend(defaultSca, clipSca, weight, localScale);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
_applyCrossData(nodeOwner, additive, weight, isFirstLayer, srcValue, desValue, crossWeight) {
|
||
var pro = nodeOwner.propertyOwner;
|
||
if (pro) {
|
||
switch (nodeOwner.type) {
|
||
case 0:
|
||
var proPat = nodeOwner.property;
|
||
var m = proPat.length - 1;
|
||
for (var j = 0; j < m; j++) {
|
||
pro = pro[proPat[j]];
|
||
if (!pro)
|
||
break;
|
||
}
|
||
var crossValue = srcValue + crossWeight * (desValue - srcValue);
|
||
nodeOwner.value = crossValue;
|
||
pro && this._applyFloat(pro, proPat[m], nodeOwner, additive, weight, isFirstLayer, crossValue);
|
||
break;
|
||
case 1:
|
||
var localPos = pro.localPosition;
|
||
var position = nodeOwner.value;
|
||
var srcX = srcValue.x, srcY = srcValue.y, srcZ = srcValue.z;
|
||
position.x = srcX + crossWeight * (desValue.x - srcX);
|
||
position.y = srcY + crossWeight * (desValue.y - srcY);
|
||
position.z = srcZ + crossWeight * (desValue.z - srcZ);
|
||
this._applyPositionAndRotationEuler(nodeOwner, additive, weight, isFirstLayer, position, localPos);
|
||
pro.localPosition = localPos;
|
||
break;
|
||
case 2:
|
||
var localRot = pro.localRotation;
|
||
var rotation = nodeOwner.value;
|
||
Quaternion.lerp(srcValue, desValue, crossWeight, rotation);
|
||
this._applyRotation(nodeOwner, additive, weight, isFirstLayer, rotation, localRot);
|
||
pro.localRotation = localRot;
|
||
break;
|
||
case 3:
|
||
var localSca = pro.localScale;
|
||
var scale = nodeOwner.value;
|
||
Utils3D.scaleBlend(srcValue, desValue, crossWeight, scale);
|
||
this._applyScale(nodeOwner, additive, weight, isFirstLayer, scale, localSca);
|
||
pro.localScale = localSca;
|
||
break;
|
||
case 4:
|
||
var localEuler = pro.localRotationEuler;
|
||
var rotationEuler = nodeOwner.value;
|
||
srcX = srcValue.x, srcY = srcValue.y, srcZ = srcValue.z;
|
||
rotationEuler.x = srcX + crossWeight * (desValue.x - srcX);
|
||
rotationEuler.y = srcY + crossWeight * (desValue.y - srcY);
|
||
rotationEuler.z = srcZ + crossWeight * (desValue.z - srcZ);
|
||
this._applyPositionAndRotationEuler(nodeOwner, additive, weight, isFirstLayer, rotationEuler, localEuler);
|
||
pro.localRotationEuler = localEuler;
|
||
break;
|
||
}
|
||
nodeOwner.updateMark = this._updateMark;
|
||
}
|
||
}
|
||
_setClipDatasToNode(stateInfo, additive, weight, isFirstLayer, controllerLayer = null) {
|
||
var realtimeDatas = stateInfo._realtimeDatas;
|
||
var nodes = stateInfo._clip._nodes;
|
||
var nodeOwners = stateInfo._nodeOwners;
|
||
for (var i = 0, n = nodes.count; i < n; i++) {
|
||
var nodeOwner = nodeOwners[i];
|
||
if (nodeOwner) {
|
||
var node = nodes.getNodeByIndex(i);
|
||
if (controllerLayer.avatarMask && (!controllerLayer.avatarMask.getTransformActive(node.nodePath)))
|
||
continue;
|
||
var pro = nodeOwner.propertyOwner;
|
||
if (pro) {
|
||
switch (nodeOwner.type) {
|
||
case 0:
|
||
var proPat = nodeOwner.property;
|
||
var m = proPat.length - 1;
|
||
for (var j = 0; j < m; j++) {
|
||
pro = pro[proPat[j]];
|
||
if (!pro)
|
||
break;
|
||
}
|
||
pro && this._applyFloat(pro, proPat[m], nodeOwner, additive, weight, isFirstLayer, realtimeDatas[i]);
|
||
break;
|
||
case 1:
|
||
var localPos = pro.localPosition;
|
||
this._applyPositionAndRotationEuler(nodeOwner, additive, weight, isFirstLayer, realtimeDatas[i], localPos);
|
||
pro.localPosition = localPos;
|
||
break;
|
||
case 2:
|
||
var localRot = pro.localRotation;
|
||
this._applyRotation(nodeOwner, additive, weight, isFirstLayer, realtimeDatas[i], localRot);
|
||
pro.localRotation = localRot;
|
||
break;
|
||
case 3:
|
||
var localSca = pro.localScale;
|
||
this._applyScale(nodeOwner, additive, weight, isFirstLayer, realtimeDatas[i], localSca);
|
||
pro.localScale = localSca;
|
||
break;
|
||
case 4:
|
||
var localEuler = pro.localRotationEuler;
|
||
this._applyPositionAndRotationEuler(nodeOwner, additive, weight, isFirstLayer, realtimeDatas[i], localEuler);
|
||
pro.localRotationEuler = localEuler;
|
||
break;
|
||
}
|
||
nodeOwner.updateMark = this._updateMark;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
_setCrossClipDatasToNode(controllerLayer, srcState, destState, crossWeight, isFirstLayer) {
|
||
var nodeOwners = controllerLayer._crossNodesOwners;
|
||
var ownerCount = controllerLayer._crossNodesOwnersCount;
|
||
var additive = controllerLayer.blendingMode !== AnimatorControllerLayer.BLENDINGMODE_OVERRIDE;
|
||
var weight = controllerLayer.defaultWeight;
|
||
var destRealtimeDatas = destState._realtimeDatas;
|
||
var destDataIndices = controllerLayer._destCrossClipNodeIndices;
|
||
var destNodeOwners = destState._nodeOwners;
|
||
var srcRealtimeDatas = srcState._realtimeDatas;
|
||
var srcDataIndices = controllerLayer._srcCrossClipNodeIndices;
|
||
var srcNodeOwners = srcState._nodeOwners;
|
||
for (var i = 0; i < ownerCount; i++) {
|
||
var nodeOwner = nodeOwners[i];
|
||
if (nodeOwner) {
|
||
var srcIndex = srcDataIndices[i];
|
||
var destIndex = destDataIndices[i];
|
||
var srcValue = srcIndex !== -1 ? srcRealtimeDatas[srcIndex] : destNodeOwners[destIndex].defaultValue;
|
||
var desValue = destIndex !== -1 ? destRealtimeDatas[destIndex] : srcNodeOwners[srcIndex].defaultValue;
|
||
this._applyCrossData(nodeOwner, additive, weight, isFirstLayer, srcValue, desValue, crossWeight);
|
||
}
|
||
}
|
||
}
|
||
_setFixedCrossClipDatasToNode(controllerLayer, destState, crossWeight, isFirstLayer) {
|
||
var nodeOwners = controllerLayer._crossNodesOwners;
|
||
var ownerCount = controllerLayer._crossNodesOwnersCount;
|
||
var additive = controllerLayer.blendingMode !== AnimatorControllerLayer.BLENDINGMODE_OVERRIDE;
|
||
var weight = controllerLayer.defaultWeight;
|
||
var destRealtimeDatas = destState._realtimeDatas;
|
||
var destDataIndices = controllerLayer._destCrossClipNodeIndices;
|
||
for (var i = 0; i < ownerCount; i++) {
|
||
var nodeOwner = nodeOwners[i];
|
||
if (nodeOwner) {
|
||
var destIndex = destDataIndices[i];
|
||
var srcValue = nodeOwner.crossFixedValue;
|
||
var desValue = destIndex !== -1 ? destRealtimeDatas[destIndex] : nodeOwner.defaultValue;
|
||
this._applyCrossData(nodeOwner, additive, weight, isFirstLayer, srcValue, desValue, crossWeight);
|
||
}
|
||
}
|
||
}
|
||
_revertDefaultKeyframeNodes(clipStateInfo) {
|
||
var nodeOwners = clipStateInfo._nodeOwners;
|
||
for (var i = 0, n = nodeOwners.length; i < n; i++) {
|
||
var nodeOwner = nodeOwners[i];
|
||
if (nodeOwner) {
|
||
var pro = nodeOwner.propertyOwner;
|
||
if (pro) {
|
||
switch (nodeOwner.type) {
|
||
case 0:
|
||
var proPat = nodeOwner.property;
|
||
var m = proPat.length - 1;
|
||
for (var j = 0; j < m; j++) {
|
||
pro = pro[proPat[j]];
|
||
if (!pro)
|
||
break;
|
||
}
|
||
pro[proPat[m]] = nodeOwner.defaultValue;
|
||
break;
|
||
case 1:
|
||
var locPos = pro.localPosition;
|
||
var def = nodeOwner.defaultValue;
|
||
locPos.x = def.x;
|
||
locPos.y = def.y;
|
||
locPos.z = def.z;
|
||
pro.localPosition = locPos;
|
||
break;
|
||
case 2:
|
||
var locRot = pro.localRotation;
|
||
var defQua = nodeOwner.defaultValue;
|
||
locRot.x = defQua.x;
|
||
locRot.y = defQua.y;
|
||
locRot.z = defQua.z;
|
||
locRot.w = defQua.w;
|
||
pro.localRotation = locRot;
|
||
break;
|
||
case 3:
|
||
var locSca = pro.localScale;
|
||
def = nodeOwner.defaultValue;
|
||
locSca.x = def.x;
|
||
locSca.y = def.y;
|
||
locSca.z = def.z;
|
||
pro.localScale = locSca;
|
||
break;
|
||
case 4:
|
||
var locEul = pro.localRotationEuler;
|
||
def = nodeOwner.defaultValue;
|
||
locEul.x = def.x;
|
||
locEul.y = def.y;
|
||
locEul.z = def.z;
|
||
pro.localRotationEuler = locEul;
|
||
break;
|
||
default:
|
||
throw "Animator:unknown type.";
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
_onAdded() {
|
||
var parent = this.owner._parent;
|
||
this.owner._setHierarchyAnimator(this, parent ? parent._hierarchyAnimator : null);
|
||
this.owner._changeAnimatorToLinkSprite3DNoAvatar(this, true, []);
|
||
}
|
||
_onDestroy() {
|
||
for (var i = 0, n = this._controllerLayers.length; i < n; i++)
|
||
this._controllerLayers[i]._removeReference();
|
||
var parent = this.owner._parent;
|
||
this.owner._clearHierarchyAnimator(this, parent ? parent._hierarchyAnimator : null);
|
||
}
|
||
_onEnable() {
|
||
this.owner._scene._animatorPool.add(this);
|
||
for (var i = 0, n = this._controllerLayers.length; i < n; i++) {
|
||
if (this._controllerLayers[i].playOnWake) {
|
||
var defaultClip = this.getDefaultState(i);
|
||
(defaultClip) && (this.play(null, i, 0));
|
||
}
|
||
}
|
||
}
|
||
_onDisable() {
|
||
this.owner._scene._animatorPool.remove(this);
|
||
}
|
||
_handleSpriteOwnersBySprite(isLink, path, sprite) {
|
||
for (var i = 0, n = this._controllerLayers.length; i < n; i++) {
|
||
var clipStateInfos = this._controllerLayers[i]._states;
|
||
for (var j = 0, m = clipStateInfos.length; j < m; j++) {
|
||
var clipStateInfo = clipStateInfos[j];
|
||
var clip = clipStateInfo._clip;
|
||
var nodePath = path.join("/");
|
||
var ownersNodes = clip._nodesMap[nodePath];
|
||
if (ownersNodes) {
|
||
var nodeOwners = clipStateInfo._nodeOwners;
|
||
for (var k = 0, p = ownersNodes.length; k < p; k++) {
|
||
if (isLink)
|
||
this._addKeyframeNodeOwner(nodeOwners, ownersNodes[k], sprite);
|
||
else
|
||
this._removeKeyframeNodeOwner(nodeOwners, ownersNodes[k]);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
_parse(data) {
|
||
var avatarData = data.avatar;
|
||
if (avatarData) {
|
||
this.avatar = Laya.Loader.getRes(avatarData.path);
|
||
var linkSprites = avatarData.linkSprites;
|
||
this._linkSprites = linkSprites;
|
||
this._linkToSprites(linkSprites);
|
||
}
|
||
var play = data.playOnWake;
|
||
var layersData = data.layers;
|
||
for (var i = 0; i < layersData.length; i++) {
|
||
var layerData = layersData[i];
|
||
var animatorLayer = new AnimatorControllerLayer(layerData.name);
|
||
if (i === 0)
|
||
animatorLayer.defaultWeight = 1.0;
|
||
else
|
||
animatorLayer.defaultWeight = layerData.weight;
|
||
var blendingModeData = layerData.blendingMode;
|
||
(blendingModeData) && (animatorLayer.blendingMode = blendingModeData);
|
||
this.addControllerLayer(animatorLayer);
|
||
var states = layerData.states;
|
||
for (var j = 0, m = states.length; j < m; j++) {
|
||
var state = states[j];
|
||
var clipPath = state.clipPath;
|
||
if (clipPath) {
|
||
var name = state.name;
|
||
var motion;
|
||
motion = Laya.Loader.getRes(clipPath);
|
||
if (motion) {
|
||
var animatorState = new AnimatorState();
|
||
animatorState.name = name;
|
||
animatorState.clip = motion;
|
||
animatorLayer.addState(animatorState);
|
||
(j === 0) && (this.getControllerLayer(i).defaultState = animatorState);
|
||
}
|
||
}
|
||
}
|
||
(play !== undefined) && (animatorLayer.playOnWake = play);
|
||
let layerMaskData = layerData.avatarMask;
|
||
if (layerMaskData) {
|
||
let avaMask = new AvatarMask(this);
|
||
animatorLayer.avatarMask = avaMask;
|
||
for (var bips in layerMaskData) {
|
||
avaMask.setTransformActive(bips, layerMaskData[bips]);
|
||
}
|
||
}
|
||
}
|
||
var cullingModeData = data.cullingMode;
|
||
(cullingModeData !== undefined) && (this.cullingMode = cullingModeData);
|
||
}
|
||
_update() {
|
||
var timer = this.owner._scene.timer;
|
||
var delta = timer._delta / 1000.0;
|
||
if (this._speed === 0 || delta === 0)
|
||
return;
|
||
var needRender;
|
||
if (this.cullingMode === Animator.CULLINGMODE_CULLCOMPLETELY) {
|
||
needRender = false;
|
||
for (var i = 0, n = this._renderableSprites.length; i < n; i++) {
|
||
if (this._renderableSprites[i]._render.isRender) {
|
||
needRender = true;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
needRender = true;
|
||
}
|
||
this._updateMark++;
|
||
for (i = 0, n = this._controllerLayers.length; i < n; i++) {
|
||
var controllerLayer = this._controllerLayers[i];
|
||
var playStateInfo = controllerLayer._playStateInfo;
|
||
var crossPlayStateInfo = controllerLayer._crossPlayStateInfo;
|
||
addtive = controllerLayer.blendingMode !== AnimatorControllerLayer.BLENDINGMODE_OVERRIDE;
|
||
switch (controllerLayer._playType) {
|
||
case 0:
|
||
var animatorState = playStateInfo._currentState;
|
||
var clip = animatorState._clip;
|
||
var speed = this._speed * animatorState.speed;
|
||
var finish = playStateInfo._finish;
|
||
finish || this._updatePlayer(animatorState, playStateInfo, delta * speed, clip.islooping);
|
||
if (needRender) {
|
||
var addtive = controllerLayer.blendingMode !== AnimatorControllerLayer.BLENDINGMODE_OVERRIDE;
|
||
this._updateClipDatas(animatorState, addtive, playStateInfo, controllerLayer.avatarMask);
|
||
this._setClipDatasToNode(animatorState, addtive, controllerLayer.defaultWeight, i === 0, controllerLayer);
|
||
finish || this._updateEventScript(animatorState, playStateInfo);
|
||
}
|
||
playStateInfo._finish && this._updateStateFinish(animatorState, playStateInfo);
|
||
break;
|
||
case 1:
|
||
animatorState = playStateInfo._currentState;
|
||
clip = animatorState._clip;
|
||
var crossState = controllerLayer._crossPlayState;
|
||
var crossClip = crossState._clip;
|
||
var crossDuratuion = controllerLayer._crossDuration;
|
||
var startPlayTime = crossPlayStateInfo._startPlayTime;
|
||
var crossClipDuration = crossClip._duration - startPlayTime;
|
||
var crossScale = crossDuratuion > crossClipDuration ? crossClipDuration / crossDuratuion : 1.0;
|
||
var crossSpeed = this._speed * crossState.speed;
|
||
this._updatePlayer(crossState, crossPlayStateInfo, delta * crossScale * crossSpeed, crossClip.islooping);
|
||
var crossWeight = ((crossPlayStateInfo._elapsedTime - startPlayTime) / crossScale) / crossDuratuion;
|
||
var needUpdateFinishcurrentState = false;
|
||
if (crossWeight >= 1.0) {
|
||
if (needRender) {
|
||
this._updateClipDatas(crossState, addtive, crossPlayStateInfo, controllerLayer.avatarMask);
|
||
this._setClipDatasToNode(crossState, addtive, controllerLayer.defaultWeight, i === 0, controllerLayer);
|
||
controllerLayer._playType = 0;
|
||
playStateInfo._currentState = crossState;
|
||
crossPlayStateInfo._cloneTo(playStateInfo);
|
||
}
|
||
}
|
||
else {
|
||
if (!playStateInfo._finish) {
|
||
speed = this._speed * animatorState.speed;
|
||
needUpdateFinishcurrentState = true;
|
||
this._updatePlayer(animatorState, playStateInfo, delta * speed, clip.islooping);
|
||
if (needRender)
|
||
this._updateClipDatas(animatorState, addtive, playStateInfo, controllerLayer.avatarMask);
|
||
}
|
||
if (needRender) {
|
||
this._updateClipDatas(crossState, addtive, crossPlayStateInfo, controllerLayer.avatarMask);
|
||
this._setCrossClipDatasToNode(controllerLayer, animatorState, crossState, crossWeight, i === 0);
|
||
}
|
||
}
|
||
if (needRender) {
|
||
this._updateEventScript(animatorState, playStateInfo);
|
||
this._updateEventScript(crossState, crossPlayStateInfo);
|
||
}
|
||
this._updateStateFinish(crossState, crossPlayStateInfo);
|
||
needUpdateFinishcurrentState && this._updateStateFinish(playStateInfo._currentState, playStateInfo);
|
||
break;
|
||
case 2:
|
||
crossState = controllerLayer._crossPlayState;
|
||
crossClip = crossState._clip;
|
||
crossDuratuion = controllerLayer._crossDuration;
|
||
startPlayTime = crossPlayStateInfo._startPlayTime;
|
||
crossClipDuration = crossClip._duration - startPlayTime;
|
||
crossScale = crossDuratuion > crossClipDuration ? crossClipDuration / crossDuratuion : 1.0;
|
||
crossSpeed = this._speed * crossState.speed;
|
||
this._updatePlayer(crossState, crossPlayStateInfo, delta * crossScale * crossSpeed, crossClip.islooping);
|
||
if (needRender) {
|
||
crossWeight = ((crossPlayStateInfo._elapsedTime - startPlayTime) / crossScale) / crossDuratuion;
|
||
if (crossWeight >= 1.0) {
|
||
this._updateClipDatas(crossState, addtive, crossPlayStateInfo, controllerLayer.avatarMask);
|
||
this._setClipDatasToNode(crossState, addtive, 1.0, i === 0, controllerLayer);
|
||
controllerLayer._playType = 0;
|
||
playStateInfo._currentState = crossState;
|
||
crossPlayStateInfo._cloneTo(playStateInfo);
|
||
}
|
||
else {
|
||
this._updateClipDatas(crossState, addtive, crossPlayStateInfo, controllerLayer.avatarMask);
|
||
this._setFixedCrossClipDatasToNode(controllerLayer, crossState, crossWeight, i === 0);
|
||
}
|
||
this._updateEventScript(crossState, crossPlayStateInfo);
|
||
}
|
||
this._updateStateFinish(crossState, crossPlayStateInfo);
|
||
break;
|
||
}
|
||
}
|
||
if (needRender) {
|
||
if (this._avatar) {
|
||
this._updateAvatarNodesToSprite();
|
||
}
|
||
}
|
||
}
|
||
_cloneTo(dest) {
|
||
var animator = dest;
|
||
animator.avatar = this.avatar;
|
||
animator.cullingMode = this.cullingMode;
|
||
for (var i = 0, n = this._controllerLayers.length; i < n; i++) {
|
||
var controllLayer = this._controllerLayers[i];
|
||
animator.addControllerLayer(controllLayer.clone());
|
||
var animatorStates = controllLayer._states;
|
||
for (var j = 0, m = animatorStates.length; j < m; j++) {
|
||
var state = animatorStates[j].clone();
|
||
var cloneLayer = animator.getControllerLayer(i);
|
||
cloneLayer.addState(state);
|
||
(j == 0) && (cloneLayer.defaultState = state);
|
||
}
|
||
}
|
||
animator._linkSprites = this._linkSprites;
|
||
animator._linkToSprites(this._linkSprites);
|
||
}
|
||
getDefaultState(layerIndex = 0) {
|
||
var controllerLayer = this._controllerLayers[layerIndex];
|
||
return controllerLayer.defaultState;
|
||
}
|
||
addState(state, layerIndex = 0) {
|
||
var controllerLayer = this._controllerLayers[layerIndex];
|
||
controllerLayer.addState(state);
|
||
console.warn("Animator:this function is discard,please use animatorControllerLayer.addState() instead.");
|
||
}
|
||
removeState(state, layerIndex = 0) {
|
||
var controllerLayer = this._controllerLayers[layerIndex];
|
||
controllerLayer.removeState(state);
|
||
console.warn("Animator:this function is discard,please use animatorControllerLayer.removeState() instead.");
|
||
}
|
||
addControllerLayer(controllderLayer) {
|
||
this._controllerLayers.push(controllderLayer);
|
||
controllderLayer._animator = this;
|
||
controllderLayer._addReference();
|
||
var states = controllderLayer._states;
|
||
for (var i = 0, n = states.length; i < n; i++)
|
||
this._getOwnersByClip(states[i]);
|
||
}
|
||
getControllerLayer(layerInex = 0) {
|
||
return this._controllerLayers[layerInex];
|
||
}
|
||
play(name = null, layerIndex = 0, normalizedTime = Number.NEGATIVE_INFINITY) {
|
||
var controllerLayer = this._controllerLayers[layerIndex];
|
||
if (controllerLayer) {
|
||
var defaultState = controllerLayer.defaultState;
|
||
if (!name && !defaultState)
|
||
throw new Error("Animator:must have default clip value,please set clip property.");
|
||
var playStateInfo = controllerLayer._playStateInfo;
|
||
var curPlayState = playStateInfo._currentState;
|
||
var animatorState = name ? controllerLayer._statesMap[name] : defaultState;
|
||
var clipDuration = animatorState._clip._duration;
|
||
var calclipduration = animatorState._clip._duration * (animatorState.clipEnd - animatorState.clipStart);
|
||
if (curPlayState !== animatorState) {
|
||
if (normalizedTime !== Number.NEGATIVE_INFINITY)
|
||
playStateInfo._resetPlayState(clipDuration * normalizedTime, calclipduration);
|
||
else
|
||
playStateInfo._resetPlayState(0.0, calclipduration);
|
||
(curPlayState !== null && curPlayState !== animatorState) && (this._revertDefaultKeyframeNodes(curPlayState));
|
||
controllerLayer._playType = 0;
|
||
playStateInfo._currentState = animatorState;
|
||
}
|
||
else {
|
||
if (normalizedTime !== Number.NEGATIVE_INFINITY) {
|
||
playStateInfo._resetPlayState(clipDuration * normalizedTime, calclipduration);
|
||
controllerLayer._playType = 0;
|
||
}
|
||
}
|
||
var scripts = animatorState._scripts;
|
||
if (scripts) {
|
||
for (var i = 0, n = scripts.length; i < n; i++)
|
||
scripts[i].onStateEnter();
|
||
}
|
||
}
|
||
else {
|
||
console.warn("Invalid layerIndex " + layerIndex + ".");
|
||
}
|
||
if (this.owner._scene) {
|
||
this._update();
|
||
}
|
||
}
|
||
crossFade(name, transitionDuration, layerIndex = 0, normalizedTime = Number.NEGATIVE_INFINITY) {
|
||
var controllerLayer = this._controllerLayers[layerIndex];
|
||
if (controllerLayer) {
|
||
var destAnimatorState = controllerLayer._statesMap[name];
|
||
if (destAnimatorState) {
|
||
var playType = controllerLayer._playType;
|
||
if (playType === -1) {
|
||
this.play(name, layerIndex, normalizedTime);
|
||
return;
|
||
}
|
||
var crossPlayStateInfo = controllerLayer._crossPlayStateInfo;
|
||
var crossNodeOwners = controllerLayer._crossNodesOwners;
|
||
var crossNodeOwnerIndicesMap = controllerLayer._crossNodesOwnersIndicesMap;
|
||
var srcAnimatorState = controllerLayer._playStateInfo._currentState;
|
||
var destNodeOwners = destAnimatorState._nodeOwners;
|
||
var destCrossClipNodeIndices = controllerLayer._destCrossClipNodeIndices;
|
||
var destClip = destAnimatorState._clip;
|
||
var destNodes = destClip._nodes;
|
||
var destNodesMap = destClip._nodesDic;
|
||
var crossCount = 0;
|
||
switch (playType) {
|
||
case 0:
|
||
var srcNodeOwners = srcAnimatorState._nodeOwners;
|
||
var scrCrossClipNodeIndices = controllerLayer._srcCrossClipNodeIndices;
|
||
var srcClip = srcAnimatorState._clip;
|
||
var srcNodes = srcClip._nodes;
|
||
var srcNodesMap = srcClip._nodesDic;
|
||
controllerLayer._playType = 1;
|
||
var crossMark = ++controllerLayer._crossMark;
|
||
crossCount = controllerLayer._crossNodesOwnersCount = 0;
|
||
for (var i = 0, n = srcNodes.count; i < n; i++) {
|
||
var srcNode = srcNodes.getNodeByIndex(i);
|
||
var srcIndex = srcNode._indexInList;
|
||
var srcNodeOwner = srcNodeOwners[srcIndex];
|
||
if (srcNodeOwner) {
|
||
var srcFullPath = srcNode.fullPath;
|
||
scrCrossClipNodeIndices[crossCount] = srcIndex;
|
||
var destNode = destNodesMap[srcFullPath];
|
||
if (destNode)
|
||
destCrossClipNodeIndices[crossCount] = destNode._indexInList;
|
||
else
|
||
destCrossClipNodeIndices[crossCount] = -1;
|
||
crossNodeOwnerIndicesMap[srcFullPath] = crossMark;
|
||
crossNodeOwners[crossCount] = srcNodeOwner;
|
||
crossCount++;
|
||
}
|
||
}
|
||
for (i = 0, n = destNodes.count; i < n; i++) {
|
||
destNode = destNodes.getNodeByIndex(i);
|
||
var destIndex = destNode._indexInList;
|
||
var destNodeOwner = destNodeOwners[destIndex];
|
||
if (destNodeOwner) {
|
||
var destFullPath = destNode.fullPath;
|
||
if (!srcNodesMap[destFullPath]) {
|
||
scrCrossClipNodeIndices[crossCount] = -1;
|
||
destCrossClipNodeIndices[crossCount] = destIndex;
|
||
crossNodeOwnerIndicesMap[destFullPath] = crossMark;
|
||
crossNodeOwners[crossCount] = destNodeOwner;
|
||
crossCount++;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
case 1:
|
||
case 2:
|
||
controllerLayer._playType = 2;
|
||
for (i = 0, n = crossNodeOwners.length; i < n; i++) {
|
||
var nodeOwner = crossNodeOwners[i];
|
||
nodeOwner.saveCrossFixedValue();
|
||
destNode = destNodesMap[nodeOwner.fullPath];
|
||
if (destNode)
|
||
destCrossClipNodeIndices[i] = destNode._indexInList;
|
||
else
|
||
destCrossClipNodeIndices[i] = -1;
|
||
}
|
||
crossCount = controllerLayer._crossNodesOwnersCount;
|
||
crossMark = controllerLayer._crossMark;
|
||
for (i = 0, n = destNodes.count; i < n; i++) {
|
||
destNode = destNodes.getNodeByIndex(i);
|
||
destIndex = destNode._indexInList;
|
||
destNodeOwner = destNodeOwners[destIndex];
|
||
if (destNodeOwner) {
|
||
destFullPath = destNode.fullPath;
|
||
if (crossNodeOwnerIndicesMap[destFullPath] !== crossMark) {
|
||
destCrossClipNodeIndices[crossCount] = destIndex;
|
||
crossNodeOwnerIndicesMap[destFullPath] = crossMark;
|
||
nodeOwner = destNodeOwners[destIndex];
|
||
crossNodeOwners[crossCount] = nodeOwner;
|
||
nodeOwner.saveCrossFixedValue();
|
||
crossCount++;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
controllerLayer._crossNodesOwnersCount = crossCount;
|
||
controllerLayer._crossPlayState = destAnimatorState;
|
||
controllerLayer._crossDuration = srcAnimatorState._clip._duration * transitionDuration;
|
||
if (normalizedTime !== Number.NEGATIVE_INFINITY)
|
||
crossPlayStateInfo._resetPlayState(destClip._duration * normalizedTime, controllerLayer._crossDuration);
|
||
else
|
||
crossPlayStateInfo._resetPlayState(0.0, controllerLayer._crossDuration);
|
||
var scripts = destAnimatorState._scripts;
|
||
if (scripts) {
|
||
for (i = 0, n = scripts.length; i < n; i++)
|
||
scripts[i].onStateEnter();
|
||
}
|
||
}
|
||
else {
|
||
console.warn("Invalid name " + layerIndex + ".");
|
||
}
|
||
}
|
||
else {
|
||
console.warn("Invalid layerIndex " + layerIndex + ".");
|
||
}
|
||
}
|
||
getCurrentAnimatorPlayState(layerInex = 0) {
|
||
return this._controllerLayers[layerInex]._playStateInfo;
|
||
}
|
||
get avatar() {
|
||
return this._avatar;
|
||
}
|
||
set avatar(value) {
|
||
if (this._avatar !== value) {
|
||
this._avatar = value;
|
||
if (value) {
|
||
this._getAvatarOwnersAndInitDatasAsync();
|
||
this.owner._changeHierarchyAnimatorAvatar(this, value);
|
||
}
|
||
else {
|
||
var parent = this.owner._parent;
|
||
this.owner._changeHierarchyAnimatorAvatar(this, parent ? parent._hierarchyAnimator._avatar : null);
|
||
}
|
||
}
|
||
}
|
||
_isLinkSpriteToAnimationNodeData(sprite, nodeName, isLink) {
|
||
var linkSprites = this._linkAvatarSpritesData[nodeName];
|
||
if (isLink) {
|
||
linkSprites || (this._linkAvatarSpritesData[nodeName] = linkSprites = []);
|
||
linkSprites.push(sprite);
|
||
}
|
||
else {
|
||
var index = linkSprites.indexOf(sprite);
|
||
linkSprites.splice(index, 1);
|
||
}
|
||
}
|
||
_getAvatarOwnersAndInitDatasAsync() {
|
||
for (var i = 0, n = this._controllerLayers.length; i < n; i++) {
|
||
var clipStateInfos = this._controllerLayers[i]._states;
|
||
for (var j = 0, m = clipStateInfos.length; j < m; j++)
|
||
this._getOwnersByClip(clipStateInfos[j]);
|
||
}
|
||
this._avatar._cloneDatasToAnimator(this);
|
||
for (var k in this._linkAvatarSpritesData) {
|
||
var sprites = this._linkAvatarSpritesData[k];
|
||
if (sprites) {
|
||
for (var c = 0, p = sprites.length; c < p; c++)
|
||
this._isLinkSpriteToAnimationNode(sprites[c], k, true);
|
||
}
|
||
}
|
||
}
|
||
_isLinkSpriteToAnimationNode(sprite, nodeName, isLink) {
|
||
if (this._avatar) {
|
||
var node = this._avatarNodeMap[nodeName];
|
||
if (node) {
|
||
if (isLink) {
|
||
sprite._transform._dummy = node.transform;
|
||
this._linkAvatarSprites.push(sprite);
|
||
var nodeTransform = node.transform;
|
||
var spriteTransform = sprite.transform;
|
||
if (!spriteTransform.owner.isStatic && nodeTransform) {
|
||
var spriteWorldMatrix = spriteTransform.worldMatrix;
|
||
var ownParTra = this.owner._transform._parent;
|
||
if (ownParTra) {
|
||
Utils3D.matrix4x4MultiplyMFM(ownParTra.worldMatrix, nodeTransform.getWorldMatrix(), spriteWorldMatrix);
|
||
}
|
||
else {
|
||
var sprWorE = spriteWorldMatrix.elements;
|
||
var nodWorE = nodeTransform.getWorldMatrix();
|
||
for (var i = 0; i < 16; i++)
|
||
sprWorE[i] = nodWorE[i];
|
||
}
|
||
spriteTransform.worldMatrix = spriteWorldMatrix;
|
||
}
|
||
}
|
||
else {
|
||
sprite._transform._dummy = null;
|
||
this._linkAvatarSprites.splice(this._linkAvatarSprites.indexOf(sprite), 1);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
_updateAvatarNodesToSprite() {
|
||
for (var i = 0, n = this._linkAvatarSprites.length; i < n; i++) {
|
||
var sprite = this._linkAvatarSprites[i];
|
||
var nodeTransform = sprite.transform._dummy;
|
||
var spriteTransform = sprite.transform;
|
||
if (!spriteTransform.owner.isStatic && nodeTransform) {
|
||
var spriteWorldMatrix = spriteTransform.worldMatrix;
|
||
var ownTra = this.owner._transform;
|
||
Utils3D.matrix4x4MultiplyMFM(ownTra.worldMatrix, nodeTransform.getWorldMatrix(), spriteWorldMatrix);
|
||
spriteTransform.worldMatrix = spriteWorldMatrix;
|
||
}
|
||
}
|
||
}
|
||
linkSprite3DToAvatarNode(nodeName, sprite3D) {
|
||
this._isLinkSpriteToAnimationNodeData(sprite3D, nodeName, true);
|
||
this._isLinkSpriteToAnimationNode(sprite3D, nodeName, true);
|
||
return true;
|
||
}
|
||
unLinkSprite3DToAvatarNode(sprite3D) {
|
||
var dummy = sprite3D.transform._dummy;
|
||
if (dummy) {
|
||
var nodeName = dummy._owner.name;
|
||
this._isLinkSpriteToAnimationNodeData(sprite3D, nodeName, false);
|
||
this._isLinkSpriteToAnimationNode(sprite3D, nodeName, false);
|
||
return true;
|
||
}
|
||
else {
|
||
return false;
|
||
}
|
||
}
|
||
_updateAnimationNodeWorldMatix(localPositions, localRotations, localScales, worldMatrixs, parentIndices) {
|
||
Laya.LayaGL.instance.updateAnimationNodeWorldMatix(localPositions, localRotations, localScales, parentIndices, worldMatrixs);
|
||
}
|
||
}
|
||
Animator._tempVector31 = new Vector3();
|
||
Animator._tempQuaternion1 = new Quaternion();
|
||
Animator.CULLINGMODE_ALWAYSANIMATE = 0;
|
||
Animator.CULLINGMODE_CULLCOMPLETELY = 2;
|
||
|
||
class RenderContext3D {
|
||
constructor() {
|
||
this.invertY = false;
|
||
this.configPipeLineMode = "Forward";
|
||
}
|
||
}
|
||
RenderContext3D._instance = new RenderContext3D();
|
||
|
||
class RenderTexture extends Laya.BaseTexture {
|
||
constructor(width, height, format = Laya.RenderTextureFormat.R8G8B8, depthStencilFormat = Laya.RenderTextureDepthFormat.DEPTH_16, mulSampler = 1) {
|
||
super(format, false);
|
||
this._inPool = false;
|
||
this._mulSampler = 1;
|
||
this._mulSamplerRT = false;
|
||
this._isCameraTarget = false;
|
||
this._glTextureType = Laya.LayaGL.instance.TEXTURE_2D;
|
||
this._width = width;
|
||
this._height = height;
|
||
this._depthStencilFormat = depthStencilFormat;
|
||
this._mipmapCount = 1;
|
||
this._mulSampler = mulSampler;
|
||
this._create(width, height);
|
||
}
|
||
static get currentActive() {
|
||
return RenderTexture._currentActive;
|
||
}
|
||
static createFromPool(width, height, format = Laya.RenderTextureFormat.R8G8B8, depthStencilFormat = Laya.RenderTextureDepthFormat.DEPTH_16, mulSamples = 1) {
|
||
var tex;
|
||
for (var i = 0, n = RenderTexture._pool.length; i < n; i++) {
|
||
tex = RenderTexture._pool[i];
|
||
if (tex._width == width && tex._height == height && tex._format == format && tex._depthStencilFormat == depthStencilFormat && tex._mulSampler == mulSamples) {
|
||
tex._inPool = false;
|
||
var end = RenderTexture._pool[n - 1];
|
||
RenderTexture._pool[i] = end;
|
||
RenderTexture._pool.length -= 1;
|
||
return tex;
|
||
}
|
||
}
|
||
tex = new RenderTexture(width, height, format, depthStencilFormat, mulSamples);
|
||
tex.lock = true;
|
||
return tex;
|
||
}
|
||
static recoverToPool(renderTexture) {
|
||
if (renderTexture._inPool)
|
||
return;
|
||
RenderTexture._pool.push(renderTexture);
|
||
renderTexture._inPool = true;
|
||
}
|
||
get depthStencilFormat() {
|
||
return this._depthStencilFormat;
|
||
}
|
||
get defaulteTexture() {
|
||
return Laya.Texture2D.grayTexture;
|
||
}
|
||
get mulSampler() {
|
||
return this._mulSampler;
|
||
}
|
||
_create(width, height) {
|
||
var gl = Laya.LayaGL.instance;
|
||
var gl2 = gl;
|
||
var glTextureType = this._glTextureType;
|
||
var layaGPU = Laya.LayaGL.layaGPUInstance;
|
||
var isWebGL2 = layaGPU._isWebGL2;
|
||
var format = this._format;
|
||
this._frameBuffer = gl.createFramebuffer();
|
||
gl.bindFramebuffer(gl.FRAMEBUFFER, this._frameBuffer);
|
||
this._mulSamplerRT = isWebGL2 && (this._mulSampler > 1);
|
||
if (format !== Laya.RenderTextureFormat.Depth && format !== Laya.RenderTextureFormat.ShadowMap) {
|
||
if (this._mulSamplerRT) {
|
||
this._mulRenderBuffer = gl2.createRenderbuffer();
|
||
gl2.bindRenderbuffer(gl2.RENDERBUFFER, this._mulRenderBuffer);
|
||
switch (format) {
|
||
case Laya.RenderTextureFormat.R8G8B8:
|
||
gl2.renderbufferStorageMultisample(gl2.RENDERBUFFER, this._mulSampler, gl2.RGB8, width, height);
|
||
break;
|
||
case Laya.RenderTextureFormat.R8G8B8A8:
|
||
gl2.renderbufferStorageMultisample(gl2.RENDERBUFFER, this._mulSampler, gl2.RGBA8, width, height);
|
||
break;
|
||
case Laya.RenderTextureFormat.Alpha8:
|
||
gl2.renderbufferStorageMultisample(gl2.RENDERBUFFER, this._mulSampler, gl2.ALPHA, width, height);
|
||
break;
|
||
case Laya.RenderTextureFormat.R16G16B16A16:
|
||
gl2.renderbufferStorageMultisample(gl2.RENDERBUFFER, this._mulSampler, gl2.RGBA16F, width, height);
|
||
break;
|
||
}
|
||
gl2.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, this._mulRenderBuffer);
|
||
}
|
||
Laya.WebGLContext.bindTexture(gl, glTextureType, this._glTexture);
|
||
switch (format) {
|
||
case Laya.RenderTextureFormat.R8G8B8:
|
||
if (isWebGL2)
|
||
gl2.texStorage2D(glTextureType, this._mipmapCount, gl2.RGB8, width, height);
|
||
else
|
||
gl.texImage2D(glTextureType, 0, gl.RGB, width, height, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
|
||
break;
|
||
case Laya.RenderTextureFormat.R8G8B8A8:
|
||
if (isWebGL2)
|
||
gl2.texStorage2D(glTextureType, this._mipmapCount, gl2.RGBA8, width, height);
|
||
else
|
||
gl.texImage2D(glTextureType, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
||
break;
|
||
case Laya.RenderTextureFormat.Alpha8:
|
||
if (isWebGL2)
|
||
gl2.texStorage2D(glTextureType, this.mipmapCount, gl2.R8, width, height);
|
||
else
|
||
gl.texImage2D(glTextureType, 0, gl.ALPHA, width, height, 0, gl.ALPHA, gl.UNSIGNED_BYTE, null);
|
||
break;
|
||
case Laya.RenderTextureFormat.R16G16B16A16:
|
||
if (isWebGL2)
|
||
gl2.texStorage2D(glTextureType, this._mipmapCount, gl2.RGBA16F, width, height);
|
||
else
|
||
gl.texImage2D(glTextureType, 0, gl.RGBA, width, height, 0, gl.RGBA, layaGPU._oesTextureHalfFloat.HALF_FLOAT_OES, null);
|
||
break;
|
||
}
|
||
if (this._mulSamplerRT) {
|
||
this._mulFrameBuffer = gl2.createFramebuffer();
|
||
gl.bindFramebuffer(gl.FRAMEBUFFER, this._mulFrameBuffer);
|
||
gl.framebufferTexture2D(gl2.FRAMEBUFFER, gl2.COLOR_ATTACHMENT0, gl2.TEXTURE_2D, this._glTexture, 0);
|
||
}
|
||
else
|
||
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this._glTexture, 0);
|
||
}
|
||
if (format == Laya.RenderTextureFormat.Depth || format == Laya.RenderTextureFormat.ShadowMap) {
|
||
gl.bindFramebuffer(gl.FRAMEBUFFER, this._frameBuffer);
|
||
Laya.WebGLContext.bindTexture(gl, glTextureType, this._glTexture);
|
||
this.filterMode = Laya.FilterMode.Point;
|
||
switch (this._depthStencilFormat) {
|
||
case Laya.RenderTextureDepthFormat.DEPTH_16:
|
||
if (isWebGL2) {
|
||
gl2.texStorage2D(glTextureType, this._mipmapCount, gl2.DEPTH_COMPONENT16, width, height);
|
||
}
|
||
else
|
||
gl.texImage2D(glTextureType, 0, gl.DEPTH_COMPONENT, width, height, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_SHORT, null);
|
||
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, this._glTexture, 0);
|
||
break;
|
||
case Laya.RenderTextureDepthFormat.DEPTHSTENCIL_24_8:
|
||
if (isWebGL2)
|
||
gl2.texStorage2D(glTextureType, this._mipmapCount, gl2.DEPTH24_STENCIL8, width, height);
|
||
else
|
||
gl.texImage2D(glTextureType, 0, gl.DEPTH_STENCIL, width, height, 0, gl.DEPTH_STENCIL, layaGPU._webgl_depth_texture.UNSIGNED_INT_24_8_WEBGL, null);
|
||
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.TEXTURE_2D, this._glTexture, 0);
|
||
break;
|
||
default:
|
||
throw "RenderTexture: depth format RenderTexture must use depthFormat with DEPTH_16 and DEPTHSTENCIL_16_8.";
|
||
}
|
||
if (isWebGL2 && format == Laya.RenderTextureFormat.ShadowMap)
|
||
gl2.texParameteri(glTextureType, gl2.TEXTURE_COMPARE_MODE, gl2.COMPARE_REF_TO_TEXTURE);
|
||
}
|
||
else {
|
||
gl.bindFramebuffer(gl.FRAMEBUFFER, this._frameBuffer);
|
||
if (this._depthStencilFormat !== Laya.RenderTextureDepthFormat.DEPTHSTENCIL_NONE) {
|
||
this._depthStencilBuffer = gl.createRenderbuffer();
|
||
gl.bindRenderbuffer(gl.RENDERBUFFER, this._depthStencilBuffer);
|
||
if (this._mulSamplerRT) {
|
||
switch (this._depthStencilFormat) {
|
||
case Laya.RenderTextureDepthFormat.DEPTH_16:
|
||
gl2.renderbufferStorageMultisample(gl.RENDERBUFFER, this._mulSampler, gl2.DEPTH_COMPONENT16, width, height);
|
||
gl2.framebufferRenderbuffer(gl.FRAMEBUFFER, gl2.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this._depthStencilBuffer);
|
||
break;
|
||
case Laya.RenderTextureDepthFormat.STENCIL_8:
|
||
gl2.renderbufferStorageMultisample(gl.RENDERBUFFER, this._mulSampler, gl2.STENCIL_INDEX8, width, height);
|
||
gl2.framebufferRenderbuffer(gl.FRAMEBUFFER, gl2.STENCIL_ATTACHMENT, gl.RENDERBUFFER, this._depthStencilBuffer);
|
||
break;
|
||
case Laya.RenderTextureDepthFormat.DEPTHSTENCIL_24_8:
|
||
gl2.renderbufferStorageMultisample(gl.RENDERBUFFER, this._mulSampler, gl2.DEPTH_STENCIL, width, height);
|
||
gl2.framebufferRenderbuffer(gl.FRAMEBUFFER, gl2.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, this._depthStencilBuffer);
|
||
break;
|
||
default:
|
||
throw "RenderTexture: unkonw depth format.";
|
||
}
|
||
}
|
||
else {
|
||
switch (this._depthStencilFormat) {
|
||
case Laya.RenderTextureDepthFormat.DEPTH_16:
|
||
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height);
|
||
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl2.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this._depthStencilBuffer);
|
||
break;
|
||
case Laya.RenderTextureDepthFormat.STENCIL_8:
|
||
gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, width, height);
|
||
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, this._depthStencilBuffer);
|
||
break;
|
||
case Laya.RenderTextureDepthFormat.DEPTHSTENCIL_24_8:
|
||
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height);
|
||
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, this._depthStencilBuffer);
|
||
break;
|
||
default:
|
||
throw "RenderTexture: unkonw depth format.";
|
||
}
|
||
}
|
||
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
|
||
}
|
||
}
|
||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||
this._setWarpMode(gl.TEXTURE_WRAP_S, this._wrapModeU);
|
||
this._setWarpMode(gl.TEXTURE_WRAP_T, this._wrapModeV);
|
||
this._setFilterMode(this._filterMode);
|
||
this._setAnisotropy(this._anisoLevel);
|
||
this._readyed = true;
|
||
this._activeResource();
|
||
this._setGPUMemory(width * height * 4);
|
||
}
|
||
_start() {
|
||
var gl = Laya.LayaGL.instance;
|
||
gl.bindFramebuffer(gl.FRAMEBUFFER, this._frameBuffer);
|
||
RenderTexture._currentActive = this;
|
||
(this._isCameraTarget) && (RenderContext3D._instance.invertY = true);
|
||
this._readyed = false;
|
||
}
|
||
_end() {
|
||
var gl = Laya.LayaGL.instance;
|
||
var gl2 = gl;
|
||
if (this._mulSamplerRT) {
|
||
gl2.bindFramebuffer(gl2.READ_FRAMEBUFFER, this._frameBuffer);
|
||
gl2.bindFramebuffer(gl2.DRAW_FRAMEBUFFER, this._mulFrameBuffer);
|
||
gl2.clearBufferfv(gl2.COLOR, 0, [0.0, 0.0, 0.0, 0.0]);
|
||
gl2.blitFramebuffer(0, 0, this.width, this.height, 0, 0, this._width, this._height, gl2.COLOR_BUFFER_BIT, gl.NEAREST);
|
||
}
|
||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||
RenderTexture._currentActive = null;
|
||
(this._isCameraTarget) && (RenderContext3D._instance.invertY = false);
|
||
this._readyed = true;
|
||
}
|
||
getData(x, y, width, height, out) {
|
||
if (Laya.Render.isConchApp && window.conchConfig.threadMode == 2) {
|
||
throw "native 2 thread mode use getDataAsync";
|
||
}
|
||
var gl = Laya.LayaGL.instance;
|
||
gl.bindFramebuffer(gl.FRAMEBUFFER, this._frameBuffer);
|
||
var canRead = (gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE);
|
||
if (!canRead) {
|
||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||
return null;
|
||
}
|
||
switch (this.format) {
|
||
case Laya.RenderTextureFormat.R8G8B8:
|
||
gl.readPixels(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, out);
|
||
break;
|
||
case Laya.RenderTextureFormat.R8G8B8A8:
|
||
gl.readPixels(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, out);
|
||
break;
|
||
case Laya.RenderTextureFormat.R16G16B16A16:
|
||
gl.readPixels(x, y, width, height, gl.RGBA, gl.FLOAT, out);
|
||
debugger;
|
||
break;
|
||
}
|
||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||
return out;
|
||
}
|
||
_disposeResource() {
|
||
if (this._frameBuffer) {
|
||
var gl = Laya.LayaGL.instance;
|
||
gl.deleteTexture(this._glTexture);
|
||
gl.deleteFramebuffer(this._frameBuffer);
|
||
gl.deleteRenderbuffer(this._depthStencilBuffer);
|
||
this._glTexture = null;
|
||
this._frameBuffer = null;
|
||
this._depthStencilBuffer = null;
|
||
this._setGPUMemory(0);
|
||
}
|
||
}
|
||
getDataAsync(x, y, width, height, callBack) {
|
||
var gl = Laya.LayaGL.instance;
|
||
gl.bindFramebuffer(gl.FRAMEBUFFER, this._frameBuffer);
|
||
gl.readPixelsAsync(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, function (data) {
|
||
callBack(new Uint8Array(data));
|
||
});
|
||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||
}
|
||
}
|
||
RenderTexture._pool = [];
|
||
|
||
class DefineDatas {
|
||
constructor() {
|
||
this._mask = [];
|
||
this._length = 0;
|
||
}
|
||
_intersectionDefineDatas(define) {
|
||
var unionMask = define._mask;
|
||
var mask = this._mask;
|
||
for (var i = this._length - 1; i >= 0; i--) {
|
||
var value = mask[i] & unionMask[i];
|
||
if (value == 0 && i == this._length - 1)
|
||
this._length--;
|
||
else
|
||
mask[i] = value;
|
||
}
|
||
}
|
||
add(define) {
|
||
var index = define._index;
|
||
var size = index + 1;
|
||
var mask = this._mask;
|
||
var maskStart = this._length;
|
||
if (maskStart < size) {
|
||
(mask.length < size) && (mask.length = size);
|
||
for (; maskStart < index; maskStart++)
|
||
mask[maskStart] = 0;
|
||
mask[index] = define._value;
|
||
this._length = size;
|
||
}
|
||
else {
|
||
mask[index] |= define._value;
|
||
}
|
||
}
|
||
remove(define) {
|
||
var index = define._index;
|
||
var mask = this._mask;
|
||
var endIndex = this._length - 1;
|
||
if (index > endIndex)
|
||
return;
|
||
var newValue = mask[index] & ~define._value;
|
||
if (index == endIndex && newValue === 0)
|
||
this._length--;
|
||
else
|
||
mask[index] = newValue;
|
||
}
|
||
addDefineDatas(define) {
|
||
var addMask = define._mask;
|
||
var size = define._length;
|
||
var mask = this._mask;
|
||
var maskStart = this._length;
|
||
if (maskStart < size) {
|
||
mask.length = size;
|
||
for (var i = 0; i < maskStart; i++)
|
||
mask[i] |= addMask[i];
|
||
for (; i < size; i++)
|
||
mask[i] = addMask[i];
|
||
this._length = size;
|
||
}
|
||
else {
|
||
for (var i = 0; i < size; i++) {
|
||
mask[i] |= addMask[i];
|
||
}
|
||
}
|
||
}
|
||
removeDefineDatas(define) {
|
||
var removeMask = define._mask;
|
||
var mask = this._mask;
|
||
var endIndex = this._length - 1;
|
||
var i = Math.min(define._length, endIndex);
|
||
for (; i >= 0; i--) {
|
||
var newValue = mask[i] & ~removeMask[i];
|
||
if (i == endIndex && newValue === 0) {
|
||
endIndex--;
|
||
this._length--;
|
||
}
|
||
else {
|
||
mask[i] = newValue;
|
||
}
|
||
}
|
||
}
|
||
has(define) {
|
||
var index = define._index;
|
||
if (index >= this._length)
|
||
return false;
|
||
return (this._mask[index] & define._value) !== 0;
|
||
}
|
||
clear() {
|
||
this._length = 0;
|
||
}
|
||
cloneTo(destObject) {
|
||
var destDefineData = destObject;
|
||
var destMask = destDefineData._mask;
|
||
var mask = this._mask;
|
||
var count = this._length;
|
||
destMask.length = count;
|
||
for (var i = 0; i < count; i++)
|
||
destMask[i] = mask[i];
|
||
destDefineData._length = count;
|
||
}
|
||
clone() {
|
||
var dest = new DefineDatas();
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
}
|
||
|
||
class VertexBuffer3D extends Laya.Buffer {
|
||
constructor(byteLength, bufferUsage, canRead = false) {
|
||
super();
|
||
this._vertexDeclaration = null;
|
||
this._float32Reader = null;
|
||
var gl = Laya.LayaGL.instance;
|
||
this._bufferUsage = bufferUsage;
|
||
this._bufferType = gl.ARRAY_BUFFER;
|
||
this._canRead = canRead;
|
||
this._byteLength = byteLength;
|
||
this.bind();
|
||
gl.bufferData(this._bufferType, this._byteLength, this._bufferUsage);
|
||
if (canRead) {
|
||
this._buffer = new Uint8Array(byteLength);
|
||
this._float32Reader = new Float32Array(this._buffer.buffer);
|
||
}
|
||
}
|
||
get vertexDeclaration() {
|
||
return this._vertexDeclaration;
|
||
}
|
||
set vertexDeclaration(value) {
|
||
this._vertexDeclaration = value;
|
||
}
|
||
get canRead() {
|
||
return this._canRead;
|
||
}
|
||
bind() {
|
||
if (Laya.Buffer._bindedVertexBuffer !== this._glBuffer) {
|
||
var gl = Laya.LayaGL.instance;
|
||
gl.bindBuffer(gl.ARRAY_BUFFER, this._glBuffer);
|
||
Laya.Buffer._bindedVertexBuffer = this._glBuffer;
|
||
return true;
|
||
}
|
||
else {
|
||
return false;
|
||
}
|
||
}
|
||
orphanStorage() {
|
||
this.bind();
|
||
Laya.LayaGL.instance.bufferData(this._bufferType, this._byteLength, this._bufferUsage);
|
||
}
|
||
setData(buffer, bufferOffset = 0, dataStartIndex = 0, dataCount = Number.MAX_SAFE_INTEGER) {
|
||
this.bind();
|
||
var needSubData = dataStartIndex !== 0 || dataCount !== Number.MAX_SAFE_INTEGER;
|
||
if (needSubData) {
|
||
var subData = new Uint8Array(buffer, dataStartIndex, dataCount);
|
||
Laya.LayaGL.instance.bufferSubData(this._bufferType, bufferOffset, subData);
|
||
if (this._canRead)
|
||
this._buffer.set(subData, bufferOffset);
|
||
}
|
||
else {
|
||
Laya.LayaGL.instance.bufferSubData(this._bufferType, bufferOffset, buffer);
|
||
if (this._canRead)
|
||
this._buffer.set(new Uint8Array(buffer), bufferOffset);
|
||
}
|
||
}
|
||
getUint8Data() {
|
||
if (this._canRead)
|
||
return this._buffer;
|
||
else
|
||
throw new Error("Can't read data from VertexBuffer with only write flag!");
|
||
}
|
||
getFloat32Data() {
|
||
if (this._canRead)
|
||
return this._float32Reader;
|
||
else
|
||
throw new Error("Can't read data from VertexBuffer with only write flag!");
|
||
}
|
||
markAsUnreadbale() {
|
||
this._canRead = false;
|
||
this._buffer = null;
|
||
this._float32Reader = null;
|
||
}
|
||
destroy() {
|
||
super.destroy();
|
||
this._buffer = null;
|
||
this._float32Reader = null;
|
||
this._vertexDeclaration = null;
|
||
this._byteLength = 0;
|
||
}
|
||
}
|
||
VertexBuffer3D.DATATYPE_FLOAT32ARRAY = 0;
|
||
VertexBuffer3D.DATATYPE_UINT8ARRAY = 1;
|
||
|
||
class VertexElementFormat {
|
||
static __init__() {
|
||
var gl = Laya.LayaGL.instance;
|
||
VertexElementFormat._elementInfos = {
|
||
"single": [1, gl.FLOAT, 0],
|
||
"vector2": [2, gl.FLOAT, 0],
|
||
"vector3": [3, gl.FLOAT, 0],
|
||
"vector4": [4, gl.FLOAT, 0],
|
||
"color": [4, gl.FLOAT, 0],
|
||
"byte4": [4, gl.UNSIGNED_BYTE, 0],
|
||
"byte3": [3, gl.UNSIGNED_BYTE, 0],
|
||
"byte2": [2, gl.UNSIGNED_BYTE, 0],
|
||
"byte": [1, gl.UNSIGNED_BYTE, 0],
|
||
"short2": [2, gl.FLOAT, 0],
|
||
"short4": [4, gl.FLOAT, 0],
|
||
"normalizedshort2": [2, gl.FLOAT, 0],
|
||
"normalizedshort4": [4, gl.FLOAT, 0],
|
||
"halfvector2": [2, gl.FLOAT, 0],
|
||
"halfvector4": [4, gl.FLOAT, 0]
|
||
};
|
||
}
|
||
static getElementInfos(element) {
|
||
var info = VertexElementFormat._elementInfos[element];
|
||
if (info)
|
||
return info;
|
||
else
|
||
throw "VertexElementFormat: this vertexElementFormat is not implement.";
|
||
}
|
||
}
|
||
VertexElementFormat.Single = "single";
|
||
VertexElementFormat.Vector2 = "vector2";
|
||
VertexElementFormat.Vector3 = "vector3";
|
||
VertexElementFormat.Vector4 = "vector4";
|
||
VertexElementFormat.Color = "color";
|
||
VertexElementFormat.Byte4 = "byte4";
|
||
VertexElementFormat.Byte3 = "byte3";
|
||
VertexElementFormat.Byte2 = "byte2";
|
||
VertexElementFormat.ByteOne = "byte";
|
||
VertexElementFormat.Short2 = "short2";
|
||
VertexElementFormat.Short4 = "short4";
|
||
VertexElementFormat.NormalizedShort2 = "normalizedshort2";
|
||
VertexElementFormat.NormalizedShort4 = "normalizedshort4";
|
||
VertexElementFormat.HalfVector2 = "halfvector2";
|
||
VertexElementFormat.HalfVector4 = "halfvector4";
|
||
|
||
class Matrix4x4 {
|
||
constructor(m11 = 1, m12 = 0, m13 = 0, m14 = 0, m21 = 0, m22 = 1, m23 = 0, m24 = 0, m31 = 0, m32 = 0, m33 = 1, m34 = 0, m41 = 0, m42 = 0, m43 = 0, m44 = 1, elements = null) {
|
||
var e = elements ? this.elements = elements : this.elements = new Float32Array(16);
|
||
e[0] = m11;
|
||
e[1] = m12;
|
||
e[2] = m13;
|
||
e[3] = m14;
|
||
e[4] = m21;
|
||
e[5] = m22;
|
||
e[6] = m23;
|
||
e[7] = m24;
|
||
e[8] = m31;
|
||
e[9] = m32;
|
||
e[10] = m33;
|
||
e[11] = m34;
|
||
e[12] = m41;
|
||
e[13] = m42;
|
||
e[14] = m43;
|
||
e[15] = m44;
|
||
}
|
||
static createRotationX(rad, out) {
|
||
var oe = out.elements;
|
||
var s = Math.sin(rad), c = Math.cos(rad);
|
||
oe[1] = oe[2] = oe[3] = oe[4] = oe[7] = oe[8] = oe[11] = oe[12] = oe[13] = oe[14] = 0;
|
||
oe[0] = oe[15] = 1;
|
||
oe[5] = oe[10] = c;
|
||
oe[6] = s;
|
||
oe[9] = -s;
|
||
}
|
||
static createRotationY(rad, out) {
|
||
var oe = out.elements;
|
||
var s = Math.sin(rad), c = Math.cos(rad);
|
||
oe[1] = oe[3] = oe[4] = oe[6] = oe[7] = oe[9] = oe[11] = oe[12] = oe[13] = oe[14] = 0;
|
||
oe[5] = oe[15] = 1;
|
||
oe[0] = oe[10] = c;
|
||
oe[2] = -s;
|
||
oe[8] = s;
|
||
}
|
||
static createRotationZ(rad, out) {
|
||
var oe = out.elements;
|
||
var s = Math.sin(rad), c = Math.cos(rad);
|
||
oe[2] = oe[3] = oe[6] = oe[7] = oe[8] = oe[9] = oe[11] = oe[12] = oe[13] = oe[14] = 0;
|
||
oe[10] = oe[15] = 1;
|
||
oe[0] = oe[5] = c;
|
||
oe[1] = s;
|
||
oe[4] = -s;
|
||
}
|
||
static createRotationYawPitchRoll(yaw, pitch, roll, result) {
|
||
Quaternion.createFromYawPitchRoll(yaw, pitch, roll, Matrix4x4._tempQuaternion);
|
||
Matrix4x4.createRotationQuaternion(Matrix4x4._tempQuaternion, result);
|
||
}
|
||
static createRotationAxis(axis, angle, result) {
|
||
var x = axis.x;
|
||
var y = axis.y;
|
||
var z = axis.z;
|
||
var cos = Math.cos(angle);
|
||
var sin = Math.sin(angle);
|
||
var xx = x * x;
|
||
var yy = y * y;
|
||
var zz = z * z;
|
||
var xy = x * y;
|
||
var xz = x * z;
|
||
var yz = y * z;
|
||
var resultE = result.elements;
|
||
resultE[3] = resultE[7] = resultE[11] = resultE[12] = resultE[13] = resultE[14] = 0;
|
||
resultE[15] = 1.0;
|
||
resultE[0] = xx + (cos * (1.0 - xx));
|
||
resultE[1] = (xy - (cos * xy)) + (sin * z);
|
||
resultE[2] = (xz - (cos * xz)) - (sin * y);
|
||
resultE[4] = (xy - (cos * xy)) - (sin * z);
|
||
resultE[5] = yy + (cos * (1.0 - yy));
|
||
resultE[6] = (yz - (cos * yz)) + (sin * x);
|
||
resultE[8] = (xz - (cos * xz)) + (sin * y);
|
||
resultE[9] = (yz - (cos * yz)) - (sin * x);
|
||
resultE[10] = zz + (cos * (1.0 - zz));
|
||
}
|
||
setRotation(rotation) {
|
||
var rotationX = rotation.x;
|
||
var rotationY = rotation.y;
|
||
var rotationZ = rotation.z;
|
||
var rotationW = rotation.w;
|
||
var xx = rotationX * rotationX;
|
||
var yy = rotationY * rotationY;
|
||
var zz = rotationZ * rotationZ;
|
||
var xy = rotationX * rotationY;
|
||
var zw = rotationZ * rotationW;
|
||
var zx = rotationZ * rotationX;
|
||
var yw = rotationY * rotationW;
|
||
var yz = rotationY * rotationZ;
|
||
var xw = rotationX * rotationW;
|
||
var e = this.elements;
|
||
e[0] = 1.0 - (2.0 * (yy + zz));
|
||
e[1] = 2.0 * (xy + zw);
|
||
e[2] = 2.0 * (zx - yw);
|
||
e[4] = 2.0 * (xy - zw);
|
||
e[5] = 1.0 - (2.0 * (zz + xx));
|
||
e[6] = 2.0 * (yz + xw);
|
||
e[8] = 2.0 * (zx + yw);
|
||
e[9] = 2.0 * (yz - xw);
|
||
e[10] = 1.0 - (2.0 * (yy + xx));
|
||
}
|
||
setPosition(position) {
|
||
var e = this.elements;
|
||
e[12] = position.x;
|
||
e[13] = position.y;
|
||
e[14] = position.z;
|
||
}
|
||
static createRotationQuaternion(rotation, result) {
|
||
var resultE = result.elements;
|
||
var rotationX = rotation.x;
|
||
var rotationY = rotation.y;
|
||
var rotationZ = rotation.z;
|
||
var rotationW = rotation.w;
|
||
var xx = rotationX * rotationX;
|
||
var yy = rotationY * rotationY;
|
||
var zz = rotationZ * rotationZ;
|
||
var xy = rotationX * rotationY;
|
||
var zw = rotationZ * rotationW;
|
||
var zx = rotationZ * rotationX;
|
||
var yw = rotationY * rotationW;
|
||
var yz = rotationY * rotationZ;
|
||
var xw = rotationX * rotationW;
|
||
resultE[3] = resultE[7] = resultE[11] = resultE[12] = resultE[13] = resultE[14] = 0;
|
||
resultE[15] = 1.0;
|
||
resultE[0] = 1.0 - (2.0 * (yy + zz));
|
||
resultE[1] = 2.0 * (xy + zw);
|
||
resultE[2] = 2.0 * (zx - yw);
|
||
resultE[4] = 2.0 * (xy - zw);
|
||
resultE[5] = 1.0 - (2.0 * (zz + xx));
|
||
resultE[6] = 2.0 * (yz + xw);
|
||
resultE[8] = 2.0 * (zx + yw);
|
||
resultE[9] = 2.0 * (yz - xw);
|
||
resultE[10] = 1.0 - (2.0 * (yy + xx));
|
||
}
|
||
static createTranslate(trans, out) {
|
||
var oe = out.elements;
|
||
oe[4] = oe[8] = oe[1] = oe[9] = oe[2] = oe[6] = oe[3] = oe[7] = oe[11] = 0;
|
||
oe[0] = oe[5] = oe[10] = oe[15] = 1;
|
||
oe[12] = trans.x;
|
||
oe[13] = trans.y;
|
||
oe[14] = trans.z;
|
||
}
|
||
static createScaling(scale, out) {
|
||
var oe = out.elements;
|
||
oe[0] = scale.x;
|
||
oe[5] = scale.y;
|
||
oe[10] = scale.z;
|
||
oe[1] = oe[4] = oe[8] = oe[12] = oe[9] = oe[13] = oe[2] = oe[6] = oe[14] = oe[3] = oe[7] = oe[11] = 0;
|
||
oe[15] = 1;
|
||
}
|
||
static multiply(left, right, out) {
|
||
var l = right.elements;
|
||
var r = left.elements;
|
||
var e = out.elements;
|
||
var l11 = l[0], l12 = l[1], l13 = l[2], l14 = l[3];
|
||
var l21 = l[4], l22 = l[5], l23 = l[6], l24 = l[7];
|
||
var l31 = l[8], l32 = l[9], l33 = l[10], l34 = l[11];
|
||
var l41 = l[12], l42 = l[13], l43 = l[14], l44 = l[15];
|
||
var r11 = r[0], r12 = r[1], r13 = r[2], r14 = r[3];
|
||
var r21 = r[4], r22 = r[5], r23 = r[6], r24 = r[7];
|
||
var r31 = r[8], r32 = r[9], r33 = r[10], r34 = r[11];
|
||
var r41 = r[12], r42 = r[13], r43 = r[14], r44 = r[15];
|
||
e[0] = (l11 * r11) + (l12 * r21) + (l13 * r31) + (l14 * r41);
|
||
e[1] = (l11 * r12) + (l12 * r22) + (l13 * r32) + (l14 * r42);
|
||
e[2] = (l11 * r13) + (l12 * r23) + (l13 * r33) + (l14 * r43);
|
||
e[3] = (l11 * r14) + (l12 * r24) + (l13 * r34) + (l14 * r44);
|
||
e[4] = (l21 * r11) + (l22 * r21) + (l23 * r31) + (l24 * r41);
|
||
e[5] = (l21 * r12) + (l22 * r22) + (l23 * r32) + (l24 * r42);
|
||
e[6] = (l21 * r13) + (l22 * r23) + (l23 * r33) + (l24 * r43);
|
||
e[7] = (l21 * r14) + (l22 * r24) + (l23 * r34) + (l24 * r44);
|
||
e[8] = (l31 * r11) + (l32 * r21) + (l33 * r31) + (l34 * r41);
|
||
e[9] = (l31 * r12) + (l32 * r22) + (l33 * r32) + (l34 * r42);
|
||
e[10] = (l31 * r13) + (l32 * r23) + (l33 * r33) + (l34 * r43);
|
||
e[11] = (l31 * r14) + (l32 * r24) + (l33 * r34) + (l34 * r44);
|
||
e[12] = (l41 * r11) + (l42 * r21) + (l43 * r31) + (l44 * r41);
|
||
e[13] = (l41 * r12) + (l42 * r22) + (l43 * r32) + (l44 * r42);
|
||
e[14] = (l41 * r13) + (l42 * r23) + (l43 * r33) + (l44 * r43);
|
||
e[15] = (l41 * r14) + (l42 * r24) + (l43 * r34) + (l44 * r44);
|
||
}
|
||
static multiplyForNative(left, right, out) {
|
||
Laya.LayaGL.instance.matrix4x4Multiply(left.elements, right.elements, out.elements);
|
||
}
|
||
static createFromQuaternion(rotation, out) {
|
||
var e = out.elements;
|
||
var x = rotation.x, y = rotation.y, z = rotation.z, w = rotation.w;
|
||
var x2 = x + x;
|
||
var y2 = y + y;
|
||
var z2 = z + z;
|
||
var xx = x * x2;
|
||
var yx = y * x2;
|
||
var yy = y * y2;
|
||
var zx = z * x2;
|
||
var zy = z * y2;
|
||
var zz = z * z2;
|
||
var wx = w * x2;
|
||
var wy = w * y2;
|
||
var wz = w * z2;
|
||
e[0] = 1 - yy - zz;
|
||
e[1] = yx + wz;
|
||
e[2] = zx - wy;
|
||
e[3] = 0;
|
||
e[4] = yx - wz;
|
||
e[5] = 1 - xx - zz;
|
||
e[6] = zy + wx;
|
||
e[7] = 0;
|
||
e[8] = zx + wy;
|
||
e[9] = zy - wx;
|
||
e[10] = 1 - xx - yy;
|
||
e[11] = 0;
|
||
e[12] = 0;
|
||
e[13] = 0;
|
||
e[14] = 0;
|
||
e[15] = 1;
|
||
}
|
||
static createAffineTransformation(trans, rot, scale, out) {
|
||
var oe = out.elements;
|
||
var x = rot.x, y = rot.y, z = rot.z, w = rot.w, x2 = x + x, y2 = y + y, z2 = z + z;
|
||
var xx = x * x2, xy = x * y2, xz = x * z2, yy = y * y2, yz = y * z2, zz = z * z2;
|
||
var wx = w * x2, wy = w * y2, wz = w * z2, sx = scale.x, sy = scale.y, sz = scale.z;
|
||
oe[0] = (1 - (yy + zz)) * sx;
|
||
oe[1] = (xy + wz) * sx;
|
||
oe[2] = (xz - wy) * sx;
|
||
oe[3] = 0;
|
||
oe[4] = (xy - wz) * sy;
|
||
oe[5] = (1 - (xx + zz)) * sy;
|
||
oe[6] = (yz + wx) * sy;
|
||
oe[7] = 0;
|
||
oe[8] = (xz + wy) * sz;
|
||
oe[9] = (yz - wx) * sz;
|
||
oe[10] = (1 - (xx + yy)) * sz;
|
||
oe[11] = 0;
|
||
oe[12] = trans.x;
|
||
oe[13] = trans.y;
|
||
oe[14] = trans.z;
|
||
oe[15] = 1;
|
||
}
|
||
static createLookAt(eye, target, up, out) {
|
||
var oE = out.elements;
|
||
var xaxis = Matrix4x4._tempVector0;
|
||
var yaxis = Matrix4x4._tempVector1;
|
||
var zaxis = Matrix4x4._tempVector2;
|
||
Vector3.subtract(eye, target, zaxis);
|
||
Vector3.normalize(zaxis, zaxis);
|
||
Vector3.cross(up, zaxis, xaxis);
|
||
Vector3.normalize(xaxis, xaxis);
|
||
Vector3.cross(zaxis, xaxis, yaxis);
|
||
oE[3] = oE[7] = oE[11] = 0;
|
||
oE[15] = 1;
|
||
oE[0] = xaxis.x;
|
||
oE[4] = xaxis.y;
|
||
oE[8] = xaxis.z;
|
||
oE[1] = yaxis.x;
|
||
oE[5] = yaxis.y;
|
||
oE[9] = yaxis.z;
|
||
oE[2] = zaxis.x;
|
||
oE[6] = zaxis.y;
|
||
oE[10] = zaxis.z;
|
||
oE[12] = -Vector3.dot(xaxis, eye);
|
||
oE[13] = -Vector3.dot(yaxis, eye);
|
||
oE[14] = -Vector3.dot(zaxis, eye);
|
||
}
|
||
static createPerspective(fov, aspect, znear, zfar, out) {
|
||
var yScale = 1.0 / Math.tan(fov * 0.5);
|
||
var xScale = yScale / aspect;
|
||
var halfWidth = znear / xScale;
|
||
var halfHeight = znear / yScale;
|
||
Matrix4x4.createPerspectiveOffCenter(-halfWidth, halfWidth, -halfHeight, halfHeight, znear, zfar, out);
|
||
}
|
||
static createPerspectiveOffCenter(left, right, bottom, top, znear, zfar, out) {
|
||
var oe = out.elements;
|
||
var zRange = zfar / (zfar - znear);
|
||
oe[1] = oe[2] = oe[3] = oe[4] = oe[6] = oe[7] = oe[12] = oe[13] = oe[15] = 0;
|
||
oe[0] = 2.0 * znear / (right - left);
|
||
oe[5] = 2.0 * znear / (top - bottom);
|
||
oe[8] = (left + right) / (right - left);
|
||
oe[9] = (top + bottom) / (top - bottom);
|
||
oe[10] = -zRange;
|
||
oe[11] = -1.0;
|
||
oe[14] = -znear * zRange;
|
||
}
|
||
static createOrthoOffCenter(left, right, bottom, top, znear, zfar, out) {
|
||
var oe = out.elements;
|
||
var zRange = 1.0 / (zfar - znear);
|
||
oe[1] = oe[2] = oe[3] = oe[4] = oe[6] = oe[8] = oe[7] = oe[9] = oe[11] = 0;
|
||
oe[15] = 1;
|
||
oe[0] = 2.0 / (right - left);
|
||
oe[5] = 2.0 / (top - bottom);
|
||
oe[10] = -zRange;
|
||
oe[12] = (left + right) / (left - right);
|
||
oe[13] = (top + bottom) / (bottom - top);
|
||
oe[14] = -znear * zRange;
|
||
}
|
||
getElementByRowColumn(row, column) {
|
||
if (row < 0 || row > 3)
|
||
throw new Error("row Rows and columns for matrices run from 0 to 3, inclusive.");
|
||
if (column < 0 || column > 3)
|
||
throw new Error("column Rows and columns for matrices run from 0 to 3, inclusive.");
|
||
return this.elements[(row * 4) + column];
|
||
}
|
||
setElementByRowColumn(row, column, value) {
|
||
if (row < 0 || row > 3)
|
||
throw new Error("row Rows and columns for matrices run from 0 to 3, inclusive.");
|
||
if (column < 0 || column > 3)
|
||
throw new Error("column Rows and columns for matrices run from 0 to 3, inclusive.");
|
||
this.elements[(row * 4) + column] = value;
|
||
}
|
||
equalsOtherMatrix(other) {
|
||
var e = this.elements;
|
||
var oe = other.elements;
|
||
return (MathUtils3D.nearEqual(e[0], oe[0]) && MathUtils3D.nearEqual(e[1], oe[1]) && MathUtils3D.nearEqual(e[2], oe[2]) && MathUtils3D.nearEqual(e[3], oe[3]) && MathUtils3D.nearEqual(e[4], oe[4]) && MathUtils3D.nearEqual(e[5], oe[5]) && MathUtils3D.nearEqual(e[6], oe[6]) && MathUtils3D.nearEqual(e[7], oe[7]) && MathUtils3D.nearEqual(e[8], oe[8]) && MathUtils3D.nearEqual(e[9], oe[9]) && MathUtils3D.nearEqual(e[10], oe[10]) && MathUtils3D.nearEqual(e[11], oe[11]) && MathUtils3D.nearEqual(e[12], oe[12]) && MathUtils3D.nearEqual(e[13], oe[13]) && MathUtils3D.nearEqual(e[14], oe[14]) && MathUtils3D.nearEqual(e[15], oe[15]));
|
||
}
|
||
decomposeTransRotScale(translation, rotation, scale) {
|
||
var rotationMatrix = Matrix4x4._tempMatrix4x4;
|
||
if (this.decomposeTransRotMatScale(translation, rotationMatrix, scale)) {
|
||
Quaternion.createFromMatrix4x4(rotationMatrix, rotation);
|
||
return true;
|
||
}
|
||
else {
|
||
rotation.identity();
|
||
return false;
|
||
}
|
||
}
|
||
decomposeTransRotMatScale(translation, rotationMatrix, scale) {
|
||
var e = this.elements;
|
||
var te = translation;
|
||
var re = rotationMatrix.elements;
|
||
var se = scale;
|
||
te.x = e[12];
|
||
te.y = e[13];
|
||
te.z = e[14];
|
||
var m11 = e[0], m12 = e[1], m13 = e[2];
|
||
var m21 = e[4], m22 = e[5], m23 = e[6];
|
||
var m31 = e[8], m32 = e[9], m33 = e[10];
|
||
var sX = se.x = Math.sqrt((m11 * m11) + (m12 * m12) + (m13 * m13));
|
||
var sY = se.y = Math.sqrt((m21 * m21) + (m22 * m22) + (m23 * m23));
|
||
var sZ = se.z = Math.sqrt((m31 * m31) + (m32 * m32) + (m33 * m33));
|
||
if (MathUtils3D.isZero(sX) || MathUtils3D.isZero(sY) || MathUtils3D.isZero(sZ)) {
|
||
re[1] = re[2] = re[3] = re[4] = re[6] = re[7] = re[8] = re[9] = re[11] = re[12] = re[13] = re[14] = 0;
|
||
re[0] = re[5] = re[10] = re[15] = 1;
|
||
return false;
|
||
}
|
||
var at = Matrix4x4._tempVector0;
|
||
at.x = m31 / sZ;
|
||
at.y = m32 / sZ;
|
||
at.z = m33 / sZ;
|
||
var tempRight = Matrix4x4._tempVector1;
|
||
tempRight.x = m11 / sX;
|
||
tempRight.y = m12 / sX;
|
||
tempRight.z = m13 / sX;
|
||
var up = Matrix4x4._tempVector2;
|
||
Vector3.cross(at, tempRight, up);
|
||
var right = Matrix4x4._tempVector1;
|
||
Vector3.cross(up, at, right);
|
||
re[3] = re[7] = re[11] = re[12] = re[13] = re[14] = 0;
|
||
re[15] = 1;
|
||
re[0] = right.x;
|
||
re[1] = right.y;
|
||
re[2] = right.z;
|
||
re[4] = up.x;
|
||
re[5] = up.y;
|
||
re[6] = up.z;
|
||
re[8] = at.x;
|
||
re[9] = at.y;
|
||
re[10] = at.z;
|
||
((re[0] * m11 + re[1] * m12 + re[2] * m13) < 0.0) && (se.x = -sX);
|
||
((re[4] * m21 + re[5] * m22 + re[6] * m23) < 0.0) && (se.y = -sY);
|
||
((re[8] * m31 + re[9] * m32 + re[10] * m33) < 0.0) && (se.z = -sZ);
|
||
return true;
|
||
}
|
||
decomposeYawPitchRoll(yawPitchRoll) {
|
||
var pitch = Math.asin(-this.elements[9]);
|
||
yawPitchRoll.y = pitch;
|
||
var test = Math.cos(pitch);
|
||
if (test > MathUtils3D.zeroTolerance) {
|
||
yawPitchRoll.z = Math.atan2(this.elements[1], this.elements[5]);
|
||
yawPitchRoll.x = Math.atan2(this.elements[8], this.elements[10]);
|
||
}
|
||
else {
|
||
yawPitchRoll.z = Math.atan2(-this.elements[4], this.elements[0]);
|
||
yawPitchRoll.x = 0.0;
|
||
}
|
||
}
|
||
normalize() {
|
||
var v = this.elements;
|
||
var c = v[0], d = v[1], e = v[2], g = Math.sqrt(c * c + d * d + e * e);
|
||
if (g) {
|
||
if (g == 1)
|
||
return;
|
||
}
|
||
else {
|
||
v[0] = 0;
|
||
v[1] = 0;
|
||
v[2] = 0;
|
||
return;
|
||
}
|
||
g = 1 / g;
|
||
v[0] = c * g;
|
||
v[1] = d * g;
|
||
v[2] = e * g;
|
||
}
|
||
transpose() {
|
||
var e, t;
|
||
e = this.elements;
|
||
t = e[1];
|
||
e[1] = e[4];
|
||
e[4] = t;
|
||
t = e[2];
|
||
e[2] = e[8];
|
||
e[8] = t;
|
||
t = e[3];
|
||
e[3] = e[12];
|
||
e[12] = t;
|
||
t = e[6];
|
||
e[6] = e[9];
|
||
e[9] = t;
|
||
t = e[7];
|
||
e[7] = e[13];
|
||
e[13] = t;
|
||
t = e[11];
|
||
e[11] = e[14];
|
||
e[14] = t;
|
||
return this;
|
||
}
|
||
invert(out) {
|
||
var ae = this.elements;
|
||
var oe = out.elements;
|
||
var a00 = ae[0], a01 = ae[1], a02 = ae[2], a03 = ae[3], a10 = ae[4], a11 = ae[5], a12 = ae[6], a13 = ae[7], a20 = ae[8], a21 = ae[9], a22 = ae[10], a23 = ae[11], a30 = ae[12], a31 = ae[13], a32 = ae[14], a33 = ae[15], b00 = a00 * a11 - a01 * a10, b01 = a00 * a12 - a02 * a10, b02 = a00 * a13 - a03 * a10, b03 = a01 * a12 - a02 * a11, b04 = a01 * a13 - a03 * a11, b05 = a02 * a13 - a03 * a12, b06 = a20 * a31 - a21 * a30, b07 = a20 * a32 - a22 * a30, b08 = a20 * a33 - a23 * a30, b09 = a21 * a32 - a22 * a31, b10 = a21 * a33 - a23 * a31, b11 = a22 * a33 - a23 * a32, det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
|
||
if (Math.abs(det) === 0.0) {
|
||
return;
|
||
}
|
||
det = 1.0 / det;
|
||
oe[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
|
||
oe[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
|
||
oe[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
|
||
oe[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
|
||
oe[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
|
||
oe[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
|
||
oe[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
|
||
oe[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
|
||
oe[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
|
||
oe[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
|
||
oe[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
|
||
oe[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
|
||
oe[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
|
||
oe[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
|
||
oe[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
|
||
oe[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
|
||
}
|
||
static billboard(objectPosition, cameraPosition, cameraUp, cameraForward, mat) {
|
||
Vector3.subtract(objectPosition, cameraPosition, Matrix4x4._tempVector0);
|
||
var lengthSq = Vector3.scalarLengthSquared(Matrix4x4._tempVector0);
|
||
if (MathUtils3D.isZero(lengthSq)) {
|
||
Vector3.scale(cameraForward, -1, Matrix4x4._tempVector1);
|
||
Matrix4x4._tempVector1.cloneTo(Matrix4x4._tempVector0);
|
||
}
|
||
else {
|
||
Vector3.scale(Matrix4x4._tempVector0, 1 / Math.sqrt(lengthSq), Matrix4x4._tempVector0);
|
||
}
|
||
Vector3.cross(cameraUp, Matrix4x4._tempVector0, Matrix4x4._tempVector2);
|
||
Vector3.normalize(Matrix4x4._tempVector2, Matrix4x4._tempVector2);
|
||
Vector3.cross(Matrix4x4._tempVector0, Matrix4x4._tempVector2, Matrix4x4._tempVector3);
|
||
var crosse = Matrix4x4._tempVector2;
|
||
var finale = Matrix4x4._tempVector3;
|
||
var diffee = Matrix4x4._tempVector0;
|
||
var obpose = objectPosition;
|
||
var mate = mat.elements;
|
||
mate[0] = crosse.x;
|
||
mate[1] = crosse.y;
|
||
mate[2] = crosse.z;
|
||
mate[3] = 0.0;
|
||
mate[4] = finale.x;
|
||
mate[5] = finale.y;
|
||
mate[6] = finale.z;
|
||
mate[7] = 0.0;
|
||
mate[8] = diffee.x;
|
||
mate[9] = diffee.y;
|
||
mate[10] = diffee.z;
|
||
mate[11] = 0.0;
|
||
mate[12] = obpose.x;
|
||
mate[13] = obpose.y;
|
||
mate[14] = obpose.z;
|
||
mate[15] = 1.0;
|
||
}
|
||
identity() {
|
||
var e = this.elements;
|
||
e[1] = e[2] = e[3] = e[4] = e[6] = e[7] = e[8] = e[9] = e[11] = e[12] = e[13] = e[14] = 0;
|
||
e[0] = e[5] = e[10] = e[15] = 1;
|
||
}
|
||
cloneTo(destObject) {
|
||
var i, s, d;
|
||
s = this.elements;
|
||
d = destObject.elements;
|
||
if (s === d) {
|
||
return;
|
||
}
|
||
for (i = 0; i < 16; ++i) {
|
||
d[i] = s[i];
|
||
}
|
||
}
|
||
clone() {
|
||
var dest = new Matrix4x4();
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
static translation(v3, out) {
|
||
var oe = out.elements;
|
||
oe[0] = oe[5] = oe[10] = oe[15] = 1;
|
||
oe[12] = v3.x;
|
||
oe[13] = v3.y;
|
||
oe[14] = v3.z;
|
||
}
|
||
getTranslationVector(out) {
|
||
var me = this.elements;
|
||
out.x = me[12];
|
||
out.y = me[13];
|
||
out.z = me[14];
|
||
}
|
||
setTranslationVector(translate) {
|
||
var me = this.elements;
|
||
var ve = translate;
|
||
me[12] = ve.x;
|
||
me[13] = ve.y;
|
||
me[14] = ve.z;
|
||
}
|
||
getForward(out) {
|
||
var me = this.elements;
|
||
out.x = -me[8];
|
||
out.y = -me[9];
|
||
out.z = -me[10];
|
||
}
|
||
setForward(forward) {
|
||
var me = this.elements;
|
||
me[8] = -forward.x;
|
||
me[9] = -forward.y;
|
||
me[10] = -forward.z;
|
||
}
|
||
getInvertFront() {
|
||
this.decomposeTransRotScale(Matrix4x4._tempVector0, Matrix4x4._tempQuaternion, Matrix4x4._tempVector1);
|
||
var scale = Matrix4x4._tempVector1;
|
||
var isInvert = scale.x < 0;
|
||
(scale.y < 0) && (isInvert = !isInvert);
|
||
(scale.z < 0) && (isInvert = !isInvert);
|
||
return isInvert;
|
||
}
|
||
}
|
||
Matrix4x4._tempMatrix4x4 = new Matrix4x4();
|
||
Matrix4x4.TEMPMatrix0 = new Matrix4x4();
|
||
Matrix4x4.TEMPMatrix1 = new Matrix4x4();
|
||
Matrix4x4._tempVector0 = new Vector3();
|
||
Matrix4x4._tempVector1 = new Vector3();
|
||
Matrix4x4._tempVector2 = new Vector3();
|
||
Matrix4x4._tempVector3 = new Vector3();
|
||
Matrix4x4._tempQuaternion = new Quaternion();
|
||
Matrix4x4.DEFAULT = new Matrix4x4();
|
||
Matrix4x4.ZERO = new Matrix4x4(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||
|
||
class ShaderData {
|
||
constructor(ownerResource = null) {
|
||
this._ownerResource = null;
|
||
this._data = null;
|
||
this._defineDatas = new DefineDatas();
|
||
this._runtimeCopyValues = [];
|
||
this._ownerResource = ownerResource;
|
||
this._initData();
|
||
}
|
||
_initData() {
|
||
this._data = {};
|
||
}
|
||
getData() {
|
||
return this._data;
|
||
}
|
||
addDefine(define) {
|
||
this._defineDatas.add(define);
|
||
}
|
||
removeDefine(define) {
|
||
this._defineDatas.remove(define);
|
||
}
|
||
hasDefine(define) {
|
||
return this._defineDatas.has(define);
|
||
}
|
||
clearDefine() {
|
||
this._defineDatas.clear();
|
||
}
|
||
getBool(index) {
|
||
return this._data[index];
|
||
}
|
||
setBool(index, value) {
|
||
this._data[index] = value;
|
||
}
|
||
getInt(index) {
|
||
return this._data[index];
|
||
}
|
||
setInt(index, value) {
|
||
this._data[index] = value;
|
||
}
|
||
getNumber(index) {
|
||
return this._data[index];
|
||
}
|
||
setNumber(index, value) {
|
||
this._data[index] = value;
|
||
}
|
||
getVector2(index) {
|
||
return this._data[index];
|
||
}
|
||
setVector2(index, value) {
|
||
this._data[index] = value;
|
||
}
|
||
getVector3(index) {
|
||
return this._data[index];
|
||
}
|
||
setVector3(index, value) {
|
||
this._data[index] = value;
|
||
}
|
||
getVector(index) {
|
||
return this._data[index];
|
||
}
|
||
setVector(index, value) {
|
||
this._data[index] = value;
|
||
}
|
||
getQuaternion(index) {
|
||
return this._data[index];
|
||
}
|
||
setQuaternion(index, value) {
|
||
this._data[index] = value;
|
||
}
|
||
getMatrix4x4(index) {
|
||
return this._data[index];
|
||
}
|
||
setMatrix4x4(index, value) {
|
||
this._data[index] = value;
|
||
}
|
||
getBuffer(shaderIndex) {
|
||
return this._data[shaderIndex];
|
||
}
|
||
setBuffer(index, value) {
|
||
this._data[index] = value;
|
||
}
|
||
setTexture(index, value) {
|
||
var lastValue = this._data[index];
|
||
this._data[index] = value ? value : Laya.Texture2D.erroTextur;
|
||
if (this._ownerResource && this._ownerResource.referenceCount > 0) {
|
||
(lastValue) && (lastValue._removeReference());
|
||
(value) && (value._addReference());
|
||
}
|
||
}
|
||
getTexture(index) {
|
||
return this._data[index];
|
||
}
|
||
setValueData(index, value) {
|
||
this._data[index] = value;
|
||
}
|
||
getValueData(index) {
|
||
return this._data[index];
|
||
}
|
||
setAttribute(index, value) {
|
||
this._data[index] = value;
|
||
}
|
||
getAttribute(index) {
|
||
return this._data[index];
|
||
}
|
||
getLength() {
|
||
return this._data.length;
|
||
}
|
||
setLength(value) {
|
||
this._data.length = value;
|
||
}
|
||
cloneTo(destObject) {
|
||
var dest = destObject;
|
||
var destData = dest._data;
|
||
for (var k in this._data) {
|
||
var value = this._data[k];
|
||
if (value != null) {
|
||
if (typeof (value) == 'number') {
|
||
destData[k] = value;
|
||
}
|
||
else if (typeof (value) == 'number') {
|
||
destData[k] = value;
|
||
}
|
||
else if (typeof (value) == "boolean") {
|
||
destData[k] = value;
|
||
}
|
||
else if (value instanceof Vector2) {
|
||
var v2 = (destData[k]) || (destData[k] = new Vector2());
|
||
value.cloneTo(v2);
|
||
destData[k] = v2;
|
||
}
|
||
else if (value instanceof Vector3) {
|
||
var v3 = (destData[k]) || (destData[k] = new Vector3());
|
||
value.cloneTo(v3);
|
||
destData[k] = v3;
|
||
}
|
||
else if (value instanceof Vector4) {
|
||
var v4 = (destData[k]) || (destData[k] = new Vector4());
|
||
value.cloneTo(v4);
|
||
destData[k] = v4;
|
||
}
|
||
else if (value instanceof Matrix4x4) {
|
||
var mat = (destData[k]) || (destData[k] = new Matrix4x4());
|
||
value.cloneTo(mat);
|
||
destData[k] = mat;
|
||
}
|
||
else if (value instanceof Laya.BaseTexture) {
|
||
destData[k] = value;
|
||
}
|
||
}
|
||
}
|
||
this._defineDatas.cloneTo(dest._defineDatas);
|
||
}
|
||
clone() {
|
||
var dest = new ShaderData();
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
cloneToForNative(destObject) {
|
||
var dest = destObject;
|
||
var diffSize = this._int32Data.length - dest._int32Data.length;
|
||
if (diffSize > 0) {
|
||
dest.needRenewArrayBufferForNative(this._int32Data.length);
|
||
}
|
||
dest._int32Data.set(this._int32Data, 0);
|
||
var destData = dest._nativeArray;
|
||
var dataCount = this._nativeArray.length;
|
||
destData.length = dataCount;
|
||
for (var i = 0; i < dataCount; i++) {
|
||
var value = this._nativeArray[i];
|
||
if (value) {
|
||
if (typeof (value) == 'number') {
|
||
destData[i] = value;
|
||
dest.setNumber(i, value);
|
||
}
|
||
else if (typeof (value) == 'number') {
|
||
destData[i] = value;
|
||
dest.setInt(i, value);
|
||
}
|
||
else if (typeof (value) == "boolean") {
|
||
destData[i] = value;
|
||
dest.setBool(i, value);
|
||
}
|
||
else if (value instanceof Vector2) {
|
||
var v2 = (destData[i]) || (destData[i] = new Vector2());
|
||
value.cloneTo(v2);
|
||
destData[i] = v2;
|
||
dest.setVector2(i, v2);
|
||
}
|
||
else if (value instanceof Vector3) {
|
||
var v3 = (destData[i]) || (destData[i] = new Vector3());
|
||
value.cloneTo(v3);
|
||
destData[i] = v3;
|
||
dest.setVector3(i, v3);
|
||
}
|
||
else if (value instanceof Vector4) {
|
||
var v4 = (destData[i]) || (destData[i] = new Vector4());
|
||
value.cloneTo(v4);
|
||
destData[i] = v4;
|
||
dest.setVector(i, v4);
|
||
}
|
||
else if (value instanceof Matrix4x4) {
|
||
var mat = (destData[i]) || (destData[i] = new Matrix4x4());
|
||
value.cloneTo(mat);
|
||
destData[i] = mat;
|
||
dest.setMatrix4x4(i, mat);
|
||
}
|
||
else if (value instanceof Laya.BaseTexture) {
|
||
destData[i] = value;
|
||
dest.setTexture(i, value);
|
||
}
|
||
}
|
||
}
|
||
this._defineDatas.cloneTo(dest._defineDatas);
|
||
}
|
||
_initDataForNative() {
|
||
var length = 8;
|
||
this._frameCount = -1;
|
||
this._runtimeCopyValues.length = 0;
|
||
this._nativeArray = [];
|
||
this._data = new ArrayBuffer(length * 4);
|
||
this._int32Data = new Int32Array(this._data);
|
||
this._float32Data = new Float32Array(this._data);
|
||
Laya.LayaGL.instance.createArrayBufferRef(this._data, Laya.LayaGL.ARRAY_BUFFER_TYPE_DATA, true);
|
||
}
|
||
needRenewArrayBufferForNative(index) {
|
||
if (index >= this._int32Data.length) {
|
||
var nByteLen = (index + 1) * 4;
|
||
var pre = this._int32Data;
|
||
var preConchRef = this._data["conchRef"];
|
||
var prePtrID = this._data["_ptrID"];
|
||
this._data = new ArrayBuffer(nByteLen);
|
||
this._int32Data = new Int32Array(this._data);
|
||
this._float32Data = new Float32Array(this._data);
|
||
this._data["conchRef"] = preConchRef;
|
||
this._data["_ptrID"] = prePtrID;
|
||
pre && this._int32Data.set(pre, 0);
|
||
var layagl = Laya.LayaGL.instance;
|
||
if (layagl.updateArrayBufferRef) {
|
||
layagl.updateArrayBufferRef(this._data['_ptrID'], preConchRef.isSyncToRender(), this._data);
|
||
}
|
||
else {
|
||
window.conch.updateArrayBufferRef(this._data['_ptrID'], preConchRef.isSyncToRender(), this._data);
|
||
}
|
||
}
|
||
}
|
||
getDataForNative() {
|
||
return this._nativeArray;
|
||
}
|
||
getIntForNative(index) {
|
||
return this._int32Data[index];
|
||
}
|
||
setIntForNative(index, value) {
|
||
this.needRenewArrayBufferForNative(index);
|
||
this._int32Data[index] = value;
|
||
this._nativeArray[index] = value;
|
||
}
|
||
getBoolForNative(index) {
|
||
return this._int32Data[index] == 1;
|
||
}
|
||
setBoolForNative(index, value) {
|
||
this.needRenewArrayBufferForNative(index);
|
||
this._int32Data[index] = value ? 1 : 0;
|
||
this._nativeArray[index] = value;
|
||
}
|
||
getNumberForNative(index) {
|
||
return this._float32Data[index];
|
||
}
|
||
setNumberForNative(index, value) {
|
||
this.needRenewArrayBufferForNative(index);
|
||
this._float32Data[index] = value;
|
||
this._nativeArray[index] = value;
|
||
}
|
||
getMatrix4x4ForNative(index) {
|
||
return this._nativeArray[index];
|
||
}
|
||
setMatrix4x4ForNative(index, value) {
|
||
this.needRenewArrayBufferForNative(index);
|
||
this._nativeArray[index] = value;
|
||
var nPtrID = this.setReferenceForNative(value.elements);
|
||
this._int32Data[index] = nPtrID;
|
||
}
|
||
getVectorForNative(index) {
|
||
return this._nativeArray[index];
|
||
}
|
||
setVectorForNative(index, value) {
|
||
this.needRenewArrayBufferForNative(index);
|
||
this._nativeArray[index] = value;
|
||
if (!value.elements) {
|
||
value.forNativeElement();
|
||
}
|
||
var nPtrID = this.setReferenceForNative(value.elements);
|
||
this._int32Data[index] = nPtrID;
|
||
}
|
||
getVector2ForNative(index) {
|
||
return this._nativeArray[index];
|
||
}
|
||
setVector2ForNative(index, value) {
|
||
this.needRenewArrayBufferForNative(index);
|
||
this._nativeArray[index] = value;
|
||
if (!value.elements) {
|
||
value.forNativeElement();
|
||
}
|
||
var nPtrID = this.setReferenceForNative(value.elements);
|
||
this._int32Data[index] = nPtrID;
|
||
}
|
||
getVector3ForNative(index) {
|
||
return this._nativeArray[index];
|
||
}
|
||
setVector3ForNative(index, value) {
|
||
this.needRenewArrayBufferForNative(index);
|
||
this._nativeArray[index] = value;
|
||
if (!value.elements) {
|
||
value.forNativeElement();
|
||
}
|
||
var nPtrID = this.setReferenceForNative(value.elements);
|
||
this._int32Data[index] = nPtrID;
|
||
}
|
||
getQuaternionForNative(index) {
|
||
return this._nativeArray[index];
|
||
}
|
||
setQuaternionForNative(index, value) {
|
||
this.needRenewArrayBufferForNative(index);
|
||
this._nativeArray[index] = value;
|
||
if (!value.elements) {
|
||
value.forNativeElement();
|
||
}
|
||
var nPtrID = this.setReferenceForNative(value.elements);
|
||
this._int32Data[index] = nPtrID;
|
||
}
|
||
getBufferForNative(shaderIndex) {
|
||
return this._nativeArray[shaderIndex];
|
||
}
|
||
setBufferForNative(index, value) {
|
||
this.needRenewArrayBufferForNative(index);
|
||
this._nativeArray[index] = value;
|
||
var nPtrID = this.setReferenceForNative(value);
|
||
this._int32Data[index] = nPtrID;
|
||
}
|
||
getAttributeForNative(index) {
|
||
return this._nativeArray[index];
|
||
}
|
||
setAttributeForNative(index, value) {
|
||
this._nativeArray[index] = value;
|
||
if (!value["_ptrID"]) {
|
||
Laya.LayaGL.instance.createArrayBufferRef(value, Laya.LayaGL.ARRAY_BUFFER_TYPE_DATA, true);
|
||
}
|
||
Laya.LayaGL.instance.syncBufferToRenderThread(value);
|
||
this._int32Data[index] = value["_ptrID"];
|
||
}
|
||
getTextureForNative(index) {
|
||
return this._nativeArray[index];
|
||
}
|
||
setTextureForNative(index, value) {
|
||
if (!value)
|
||
return;
|
||
this.needRenewArrayBufferForNative(index);
|
||
var lastValue = this._nativeArray[index];
|
||
this._nativeArray[index] = value;
|
||
var glTexture = value._getSource() || value.defaulteTexture._getSource();
|
||
this._int32Data[index] = glTexture.id;
|
||
if (this._ownerResource && this._ownerResource.referenceCount > 0) {
|
||
(lastValue) && (lastValue._removeReference());
|
||
(value) && (value._addReference());
|
||
}
|
||
}
|
||
setReferenceForNative(value) {
|
||
this.clearRuntimeCopyArray();
|
||
var nRefID = 0;
|
||
var nPtrID = 0;
|
||
if (ShaderData._SET_RUNTIME_VALUE_MODE_REFERENCE_) {
|
||
Laya.LayaGL.instance.createArrayBufferRefs(value, Laya.LayaGL.ARRAY_BUFFER_TYPE_DATA, true, Laya.LayaGL.ARRAY_BUFFER_REF_REFERENCE);
|
||
nRefID = 0;
|
||
nPtrID = value.getPtrID(nRefID);
|
||
}
|
||
else {
|
||
Laya.LayaGL.instance.createArrayBufferRefs(value, Laya.LayaGL.ARRAY_BUFFER_TYPE_DATA, true, Laya.LayaGL.ARRAY_BUFFER_REF_COPY);
|
||
nRefID = value.getRefNum() - 1;
|
||
nPtrID = value.getPtrID(nRefID);
|
||
this._runtimeCopyValues.push({ "obj": value, "refID": nRefID, "ptrID": nPtrID });
|
||
}
|
||
Laya.LayaGL.instance.syncBufferToRenderThread(value, nRefID);
|
||
return nPtrID;
|
||
}
|
||
static setRuntimeValueMode(bReference) {
|
||
ShaderData._SET_RUNTIME_VALUE_MODE_REFERENCE_ = bReference;
|
||
}
|
||
clearRuntimeCopyArray() {
|
||
var currentFrame = Laya.Stat.loopCount;
|
||
if (this._frameCount != currentFrame) {
|
||
this._frameCount = currentFrame;
|
||
for (var i = 0, n = this._runtimeCopyValues.length; i < n; i++) {
|
||
var obj = this._runtimeCopyValues[i];
|
||
obj.obj.clearRefNum();
|
||
}
|
||
this._runtimeCopyValues.length = 0;
|
||
}
|
||
}
|
||
}
|
||
ShaderData._SET_RUNTIME_VALUE_MODE_REFERENCE_ = true;
|
||
|
||
class VertexDeclaration {
|
||
constructor(vertexStride, vertexElements) {
|
||
this._id = ++VertexDeclaration._uniqueIDCounter;
|
||
this._vertexElementsDic = {};
|
||
this._vertexStride = vertexStride;
|
||
this._vertexElements = vertexElements;
|
||
var count = vertexElements.length;
|
||
this._shaderValues = new ShaderData(null);
|
||
for (var j = 0; j < count; j++) {
|
||
var vertexElement = vertexElements[j];
|
||
var name = vertexElement._elementUsage;
|
||
this._vertexElementsDic[name] = vertexElement;
|
||
var value = new Int32Array(5);
|
||
var elmentInfo = VertexElementFormat.getElementInfos(vertexElement._elementFormat);
|
||
value[0] = elmentInfo[0];
|
||
value[1] = elmentInfo[1];
|
||
value[2] = elmentInfo[2];
|
||
value[3] = this._vertexStride;
|
||
value[4] = vertexElement._offset;
|
||
this._shaderValues.setAttribute(name, value);
|
||
}
|
||
}
|
||
get id() {
|
||
return this._id;
|
||
}
|
||
get vertexStride() {
|
||
return this._vertexStride;
|
||
}
|
||
get vertexElementCount() {
|
||
return this._vertexElements.length;
|
||
}
|
||
getVertexElementByIndex(index) {
|
||
return this._vertexElements[index];
|
||
}
|
||
getVertexElementByUsage(usage) {
|
||
return this._vertexElementsDic[usage];
|
||
}
|
||
}
|
||
VertexDeclaration._uniqueIDCounter = 1;
|
||
|
||
class VertexElement {
|
||
constructor(offset, elementFormat, elementUsage) {
|
||
this._offset = offset;
|
||
this._elementFormat = elementFormat;
|
||
this._elementUsage = elementUsage;
|
||
}
|
||
get offset() {
|
||
return this._offset;
|
||
}
|
||
get elementFormat() {
|
||
return this._elementFormat;
|
||
}
|
||
get elementUsage() {
|
||
return this._elementUsage;
|
||
}
|
||
}
|
||
|
||
class BufferState extends Laya.BufferStateBase {
|
||
constructor() {
|
||
super();
|
||
}
|
||
applyVertexBuffer(vertexBuffer) {
|
||
if (Laya.BufferStateBase._curBindedBufferState === this) {
|
||
var gl = Laya.LayaGL.instance;
|
||
var verDec = vertexBuffer.vertexDeclaration;
|
||
var valueData = verDec._shaderValues.getData();
|
||
this.vertexDeclaration = verDec;
|
||
vertexBuffer.bind();
|
||
for (var k in valueData) {
|
||
var loc = parseInt(k);
|
||
var attribute = valueData[k];
|
||
gl.enableVertexAttribArray(loc);
|
||
gl.vertexAttribPointer(loc, attribute[0], attribute[1], !!attribute[2], attribute[3], attribute[4]);
|
||
}
|
||
}
|
||
else {
|
||
throw "BufferState: must call bind() function first.";
|
||
}
|
||
}
|
||
applyVertexBuffers(vertexBuffers) {
|
||
if (Laya.BufferStateBase._curBindedBufferState === this) {
|
||
var gl = Laya.LayaGL.instance;
|
||
for (var i = 0, n = vertexBuffers.length; i < n; i++) {
|
||
var verBuf = vertexBuffers[i];
|
||
var verDec = verBuf.vertexDeclaration;
|
||
var valueData = verDec._shaderValues.getData();
|
||
verBuf.bind();
|
||
for (var k in valueData) {
|
||
var loc = parseInt(k);
|
||
var attribute = valueData[k];
|
||
gl.enableVertexAttribArray(loc);
|
||
gl.vertexAttribPointer(loc, attribute[0], attribute[1], !!attribute[2], attribute[3], attribute[4]);
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
throw "BufferState: must call bind() function first.";
|
||
}
|
||
}
|
||
applyInstanceVertexBuffer(vertexBuffer) {
|
||
if (Laya.LayaGL.layaGPUInstance.supportInstance()) {
|
||
if (Laya.BufferStateBase._curBindedBufferState === this) {
|
||
var gl = Laya.LayaGL.instance;
|
||
var verDec = vertexBuffer.vertexDeclaration;
|
||
var valueData = verDec._shaderValues.getData();
|
||
vertexBuffer.bind();
|
||
for (var k in valueData) {
|
||
var loc = parseInt(k);
|
||
var attribute = valueData[k];
|
||
gl.enableVertexAttribArray(loc);
|
||
gl.vertexAttribPointer(loc, attribute[0], attribute[1], !!attribute[2], attribute[3], attribute[4]);
|
||
Laya.LayaGL.layaGPUInstance.vertexAttribDivisor(loc, 1);
|
||
}
|
||
}
|
||
else {
|
||
throw "BufferState: must call bind() function first.";
|
||
}
|
||
}
|
||
}
|
||
applyIndexBuffer(indexBuffer) {
|
||
if (Laya.BufferStateBase._curBindedBufferState === this) {
|
||
if (this._bindedIndexBuffer !== indexBuffer) {
|
||
indexBuffer._bindForVAO();
|
||
this._bindedIndexBuffer = indexBuffer;
|
||
}
|
||
}
|
||
else {
|
||
throw "BufferState: must call bind() function first.";
|
||
}
|
||
}
|
||
}
|
||
|
||
class ScreenQuad extends Laya.Resource {
|
||
constructor() {
|
||
super();
|
||
this._bufferState = new BufferState();
|
||
this._bufferStateInvertUV = new BufferState();
|
||
var gl = Laya.LayaGL.instance;
|
||
this._vertexBuffer = new VertexBuffer3D(16 * 4, gl.STATIC_DRAW, false);
|
||
this._vertexBuffer.vertexDeclaration = ScreenQuad._vertexDeclaration;
|
||
this._vertexBuffer.setData(ScreenQuad._vertices.buffer);
|
||
this._bufferState.bind();
|
||
this._bufferState.applyVertexBuffer(this._vertexBuffer);
|
||
this._bufferState.unBind();
|
||
this._vertexBufferInvertUV = new VertexBuffer3D(16 * 4, gl.STATIC_DRAW, false);
|
||
this._vertexBufferInvertUV.vertexDeclaration = ScreenQuad._vertexDeclaration;
|
||
this._vertexBufferInvertUV.setData(ScreenQuad._verticesInvertUV.buffer);
|
||
this._bufferStateInvertUV.bind();
|
||
this._bufferStateInvertUV.applyVertexBuffer(this._vertexBufferInvertUV);
|
||
this._bufferStateInvertUV.unBind();
|
||
this._setGPUMemory(this._vertexBuffer._byteLength + this._vertexBufferInvertUV._byteLength);
|
||
}
|
||
static __init__() {
|
||
ScreenQuad._vertexDeclaration = new VertexDeclaration(16, [new VertexElement(0, VertexElementFormat.Vector4, ScreenQuad.SCREENQUAD_POSITION_UV)]);
|
||
ScreenQuad.instance = new ScreenQuad();
|
||
ScreenQuad.instance.lock = true;
|
||
}
|
||
render() {
|
||
var gl = Laya.LayaGL.instance;
|
||
this._bufferState.bind();
|
||
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
||
Laya.Stat.renderBatches++;
|
||
}
|
||
renderInvertUV() {
|
||
var gl = Laya.LayaGL.instance;
|
||
this._bufferStateInvertUV.bind();
|
||
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
||
Laya.Stat.renderBatches++;
|
||
}
|
||
destroy() {
|
||
super.destroy();
|
||
this._bufferState.destroy();
|
||
this._vertexBuffer.destroy();
|
||
this._bufferStateInvertUV.destroy();
|
||
this._vertexBufferInvertUV.destroy();
|
||
this._setGPUMemory(0);
|
||
}
|
||
}
|
||
ScreenQuad.SCREENQUAD_POSITION_UV = 0;
|
||
ScreenQuad._vertices = new Float32Array([1, 1, 1, 1, 1, -1, 1, 0, -1, 1, 0, 1, -1, -1, 0, 0]);
|
||
ScreenQuad._verticesInvertUV = new Float32Array([1, 1, 1, 0, 1, -1, 1, 1, -1, 1, 0, 0, -1, -1, 0, 1]);
|
||
|
||
class ScreenTriangle extends Laya.Resource {
|
||
constructor() {
|
||
super();
|
||
this._bufferState = new BufferState();
|
||
this._bufferStateInvertUV = new BufferState();
|
||
var gl = Laya.LayaGL.instance;
|
||
this._vertexBuffer = new VertexBuffer3D(12 * 4, gl.STATIC_DRAW, false);
|
||
this._vertexBuffer.vertexDeclaration = ScreenTriangle._vertexDeclaration;
|
||
this._vertexBuffer.setData(ScreenTriangle._vertices.buffer);
|
||
this._bufferState.bind();
|
||
this._bufferState.applyVertexBuffer(this._vertexBuffer);
|
||
this._bufferState.unBind();
|
||
this._vertexBufferInvertUV = new VertexBuffer3D(12 * 4, gl.STATIC_DRAW, false);
|
||
this._vertexBufferInvertUV.vertexDeclaration = ScreenTriangle._vertexDeclaration;
|
||
this._vertexBufferInvertUV.setData(ScreenTriangle._verticesInvertUV.buffer);
|
||
this._bufferStateInvertUV.bind();
|
||
this._bufferStateInvertUV.applyVertexBuffer(this._vertexBufferInvertUV);
|
||
this._bufferStateInvertUV.unBind();
|
||
this._setGPUMemory(this._vertexBuffer._byteLength + this._vertexBufferInvertUV._byteLength);
|
||
}
|
||
static __init__() {
|
||
ScreenTriangle._vertexDeclaration = new VertexDeclaration(16, [new VertexElement(0, VertexElementFormat.Vector4, ScreenTriangle.SCREENTRIANGLE_POSITION_UV)]);
|
||
ScreenTriangle.instance = new ScreenTriangle();
|
||
ScreenTriangle.instance.lock = true;
|
||
}
|
||
render() {
|
||
var gl = Laya.LayaGL.instance;
|
||
this._bufferState.bind();
|
||
gl.drawArrays(gl.TRIANGLES, 0, 3);
|
||
Laya.Stat.renderBatches++;
|
||
}
|
||
renderInvertUV() {
|
||
var gl = Laya.LayaGL.instance;
|
||
this._bufferStateInvertUV.bind();
|
||
gl.drawArrays(gl.TRIANGLES, 0, 3);
|
||
Laya.Stat.renderBatches++;
|
||
}
|
||
destroy() {
|
||
super.destroy();
|
||
this._bufferState.destroy();
|
||
this._vertexBuffer.destroy();
|
||
this._bufferStateInvertUV.destroy();
|
||
this._vertexBufferInvertUV.destroy();
|
||
this._setGPUMemory(0);
|
||
}
|
||
}
|
||
ScreenTriangle.SCREENTRIANGLE_POSITION_UV = 0;
|
||
ScreenTriangle._vertices = new Float32Array([-1, -1, 0, 0, -1, 3, 0, 2, 3, -1, 2, 0]);
|
||
ScreenTriangle._verticesInvertUV = new Float32Array([-1, -1, 0, 1, -1, 3, 0, -1, 3, -1, 2, 1]);
|
||
|
||
class ShaderDefine {
|
||
constructor(index, value) {
|
||
this._index = index;
|
||
this._value = value;
|
||
}
|
||
}
|
||
|
||
class ShaderVariant {
|
||
constructor(shader, subShaderIndex, passIndex, defines) {
|
||
this._subShaderIndex = 0;
|
||
this._passIndex = 0;
|
||
this.setValue(shader, subShaderIndex, passIndex, defines);
|
||
}
|
||
get shader() {
|
||
return this._shader;
|
||
}
|
||
get subShaderIndex() {
|
||
return this._subShaderIndex;
|
||
}
|
||
get passIndex() {
|
||
return this._passIndex;
|
||
}
|
||
get defineNames() {
|
||
return this._defineNames;
|
||
}
|
||
setValue(shader, subShaderIndex, passIndex, defineNames) {
|
||
if (shader) {
|
||
var subShader = shader.getSubShaderAt(subShaderIndex);
|
||
if (subShader) {
|
||
var pass = subShader._passes[passIndex];
|
||
if (pass) {
|
||
var validDefine = pass._validDefine;
|
||
for (var i = 0, n = defineNames.length; i < n; i++) {
|
||
var defname = defineNames[i];
|
||
if (!validDefine.has(ILaya3D.Shader3D.getDefineByName(defname)))
|
||
throw `ShaderVariantInfo:Invalid defineName ${defname} in ${shader._name} subShaderIndex of ${subShaderIndex} passIndex of ${passIndex}.`;
|
||
}
|
||
}
|
||
else {
|
||
throw `ShaderVariantInfo:Shader don't have passIndex of ${passIndex}.`;
|
||
}
|
||
}
|
||
else {
|
||
throw `ShaderVariantInfo:Shader don't have subShaderIndex of ${subShaderIndex}.`;
|
||
}
|
||
}
|
||
else {
|
||
throw `ShaderVariantInfo:Shader can't be null.`;
|
||
}
|
||
this._shader = shader;
|
||
this._subShaderIndex = subShaderIndex;
|
||
this._passIndex = passIndex;
|
||
this._defineNames = defineNames;
|
||
}
|
||
equal(other) {
|
||
if (this._shader !== other._shader || this._subShaderIndex !== other._subShaderIndex || this._passIndex !== other._passIndex)
|
||
return false;
|
||
var defines = this._defineNames;
|
||
var otherDefines = other._defineNames;
|
||
if (defines.length !== otherDefines.length)
|
||
return false;
|
||
for (var i = 0, n = this._defineNames.length; i < n; i++) {
|
||
if (defines[i] !== otherDefines[i])
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
clone() {
|
||
var dest = new ShaderVariant(this._shader, this._subShaderIndex, this._passIndex, this._defineNames.slice());
|
||
return dest;
|
||
}
|
||
}
|
||
class ShaderVariantCollection {
|
||
constructor() {
|
||
this._allCompiled = false;
|
||
this._variants = [];
|
||
}
|
||
get allCompiled() {
|
||
return this._allCompiled;
|
||
}
|
||
get variantCount() {
|
||
return this._variants.length;
|
||
}
|
||
add(variant) {
|
||
for (var i = 0, n = this._variants.length; i < n; i++) {
|
||
if (this._variants[i].equal(variant))
|
||
return false;
|
||
}
|
||
this._variants.push(variant.clone());
|
||
this._allCompiled = false;
|
||
return true;
|
||
}
|
||
remove(variant) {
|
||
for (var i = 0, n = this._variants.length; i < n; i++) {
|
||
if (this._variants[i].equal(variant)) {
|
||
this._variants.splice(i, 1);
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
contatins(variant) {
|
||
for (var i = 0, n = this._variants.length; i < n; i++) {
|
||
if (this._variants[i].equal(variant))
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
getByIndex(index) {
|
||
return this._variants[index];
|
||
}
|
||
clear() {
|
||
this._variants.length = 0;
|
||
}
|
||
compile() {
|
||
if (!this._allCompiled) {
|
||
var variants = this._variants;
|
||
for (var i = 0, n = variants.length; i < n; i++) {
|
||
var variant = variants[i];
|
||
ILaya3D.Shader3D.compileShaderByDefineNames(variant._shader._name, variant._subShaderIndex, variant._passIndex, variant._defineNames);
|
||
}
|
||
this._allCompiled = true;
|
||
}
|
||
}
|
||
}
|
||
|
||
class Shader3D {
|
||
constructor(name, attributeMap, uniformMap, enableInstancing, supportReflectionProbe) {
|
||
this._attributeMap = null;
|
||
this._uniformMap = null;
|
||
this._enableInstancing = false;
|
||
this._supportReflectionProbe = false;
|
||
this._subShaders = [];
|
||
this._name = name;
|
||
this._attributeMap = attributeMap;
|
||
this._uniformMap = uniformMap;
|
||
this._enableInstancing = enableInstancing;
|
||
this._supportReflectionProbe = supportReflectionProbe;
|
||
}
|
||
static _getNamesByDefineData(defineData, out) {
|
||
var maskMap = Shader3D._maskMap;
|
||
var mask = defineData._mask;
|
||
out.length = 0;
|
||
for (var i = 0, n = defineData._length; i < n; i++) {
|
||
var subMaskMap = maskMap[i];
|
||
var subMask = mask[i];
|
||
for (var j = 0; j < 32; j++) {
|
||
var d = 1 << j;
|
||
if (subMask > 0 && d > subMask)
|
||
break;
|
||
if (subMask & d)
|
||
out.push(subMaskMap[d]);
|
||
}
|
||
}
|
||
}
|
||
static getDefineByName(name) {
|
||
var define = Shader3D._defineMap[name];
|
||
if (!define) {
|
||
var maskMap = Shader3D._maskMap;
|
||
var counter = Shader3D._defineCounter;
|
||
var index = Math.floor(counter / 32);
|
||
var value = 1 << counter % 32;
|
||
define = new ShaderDefine(index, value);
|
||
Shader3D._defineMap[name] = define;
|
||
if (index == maskMap.length) {
|
||
maskMap.length++;
|
||
maskMap[index] = {};
|
||
}
|
||
maskMap[index][value] = name;
|
||
Shader3D._defineCounter++;
|
||
}
|
||
return define;
|
||
}
|
||
static propertyNameToID(name) {
|
||
if (Shader3D._propertyNameMap[name] != null) {
|
||
return Shader3D._propertyNameMap[name];
|
||
}
|
||
else {
|
||
var id = Shader3D._propertyNameCounter++;
|
||
Shader3D._propertyNameMap[name] = id;
|
||
Shader3D._propertyNameMap[id] = name;
|
||
return id;
|
||
}
|
||
}
|
||
static addInclude(fileName, txt) {
|
||
txt = txt.replace(Laya.ShaderCompile._clearCR, "");
|
||
Laya.ShaderCompile.addInclude(fileName, txt);
|
||
}
|
||
static compileShaderByDefineNames(shaderName, subShaderIndex, passIndex, defineNames) {
|
||
var shader = Shader3D.find(shaderName);
|
||
if (shader) {
|
||
var subShader = shader.getSubShaderAt(subShaderIndex);
|
||
if (subShader) {
|
||
var pass = subShader._passes[passIndex];
|
||
if (pass) {
|
||
var compileDefineDatas = Shader3D._compileDefineDatas;
|
||
compileDefineDatas.clear();
|
||
for (var i = 0, n = defineNames.length; i < n; i++)
|
||
compileDefineDatas.add(Shader3D.getDefineByName(defineNames[i]));
|
||
pass.withCompile(compileDefineDatas);
|
||
}
|
||
else {
|
||
console.warn("Shader3D: unknown passIndex.");
|
||
}
|
||
}
|
||
else {
|
||
console.warn("Shader3D: unknown subShaderIndex.");
|
||
}
|
||
}
|
||
else {
|
||
console.warn("Shader3D: unknown shader name.");
|
||
}
|
||
}
|
||
static add(name, attributeMap = null, uniformMap = null, enableInstancing = false, supportReflectionProbe = false) {
|
||
return Shader3D._preCompileShader[name] = new Shader3D(name, attributeMap, uniformMap, enableInstancing, supportReflectionProbe);
|
||
}
|
||
static find(name) {
|
||
return Shader3D._preCompileShader[name];
|
||
}
|
||
get name() {
|
||
return this._name;
|
||
}
|
||
addSubShader(subShader) {
|
||
this._subShaders.push(subShader);
|
||
subShader._owner = this;
|
||
}
|
||
getSubShaderAt(index) {
|
||
return this._subShaders[index];
|
||
}
|
||
static compileShader(shaderName, subShaderIndex, passIndex, ...defineMask) {
|
||
var shader = Shader3D.find(shaderName);
|
||
if (shader) {
|
||
var subShader = shader.getSubShaderAt(subShaderIndex);
|
||
if (subShader) {
|
||
var pass = subShader._passes[passIndex];
|
||
if (pass) {
|
||
var compileDefineDatas = Shader3D._compileDefineDatas;
|
||
var mask = compileDefineDatas._mask;
|
||
mask.length = 0;
|
||
for (var i = 0, n = defineMask.length; i < n; i++)
|
||
mask.push(defineMask[i]);
|
||
compileDefineDatas._length = defineMask.length;
|
||
pass.withCompile(compileDefineDatas);
|
||
}
|
||
else {
|
||
console.warn("Shader3D: unknown passIndex.");
|
||
}
|
||
}
|
||
else {
|
||
console.warn("Shader3D: unknown subShaderIndex.");
|
||
}
|
||
}
|
||
else {
|
||
console.warn("Shader3D: unknown shader name.");
|
||
}
|
||
}
|
||
}
|
||
Shader3D._compileDefineDatas = new DefineDatas();
|
||
Shader3D.RENDER_STATE_CULL = 0;
|
||
Shader3D.RENDER_STATE_BLEND = 1;
|
||
Shader3D.RENDER_STATE_BLEND_SRC = 2;
|
||
Shader3D.RENDER_STATE_BLEND_DST = 3;
|
||
Shader3D.RENDER_STATE_BLEND_SRC_RGB = 4;
|
||
Shader3D.RENDER_STATE_BLEND_DST_RGB = 5;
|
||
Shader3D.RENDER_STATE_BLEND_SRC_ALPHA = 6;
|
||
Shader3D.RENDER_STATE_BLEND_DST_ALPHA = 7;
|
||
Shader3D.RENDER_STATE_BLEND_CONST_COLOR = 8;
|
||
Shader3D.RENDER_STATE_BLEND_EQUATION = 9;
|
||
Shader3D.RENDER_STATE_BLEND_EQUATION_RGB = 10;
|
||
Shader3D.RENDER_STATE_BLEND_EQUATION_ALPHA = 11;
|
||
Shader3D.RENDER_STATE_DEPTH_TEST = 12;
|
||
Shader3D.RENDER_STATE_DEPTH_WRITE = 13;
|
||
Shader3D.PERIOD_CUSTOM = 0;
|
||
Shader3D.PERIOD_MATERIAL = 1;
|
||
Shader3D.PERIOD_SPRITE = 2;
|
||
Shader3D.PERIOD_CAMERA = 3;
|
||
Shader3D.PERIOD_SCENE = 4;
|
||
Shader3D._propertyNameMap = {};
|
||
Shader3D._propertyNameCounter = 0;
|
||
Shader3D._defineCounter = 0;
|
||
Shader3D._defineMap = {};
|
||
Shader3D._preCompileShader = {};
|
||
Shader3D._maskMap = [];
|
||
Shader3D.debugMode = false;
|
||
Shader3D.debugShaderVariantCollection = new ShaderVariantCollection();
|
||
|
||
class Command {
|
||
constructor() {
|
||
this._commandBuffer = null;
|
||
}
|
||
static __init__() {
|
||
Command._screenShaderData = new ShaderData();
|
||
Command._screenShader = Shader3D.find("BlitScreen");
|
||
}
|
||
run() {
|
||
}
|
||
recover() {
|
||
this._commandBuffer = null;
|
||
}
|
||
setContext(context) {
|
||
this._context = context;
|
||
}
|
||
}
|
||
Command.SCREENTEXTURE_NAME = "u_MainTex";
|
||
Command.SCREENTEXTUREOFFSETSCALE_NAME = "u_OffsetScale";
|
||
Command.MAINTEXTURE_TEXELSIZE_NAME = "u_MainTex_TexelSize";
|
||
Command.SCREENTEXTURE_ID = Shader3D.propertyNameToID(Command.SCREENTEXTURE_NAME);
|
||
Command.SCREENTEXTUREOFFSETSCALE_ID = Shader3D.propertyNameToID(Command.SCREENTEXTUREOFFSETSCALE_NAME);
|
||
Command.MAINTEXTURE_TEXELSIZE_ID = Shader3D.propertyNameToID(Command.MAINTEXTURE_TEXELSIZE_NAME);
|
||
|
||
class BlitScreenQuadCMD extends Command {
|
||
constructor() {
|
||
super(...arguments);
|
||
this._source = null;
|
||
this._dest = null;
|
||
this._offsetScale = null;
|
||
this._shader = null;
|
||
this._shaderData = null;
|
||
this._subShader = 0;
|
||
this._sourceTexelSize = new Vector4();
|
||
this._screenType = 0;
|
||
this._drawDefineCavans = false;
|
||
}
|
||
static create(source, dest, offsetScale = null, shader = null, shaderData = null, subShader = 0, screenType = BlitScreenQuadCMD._SCREENTYPE_QUAD, commandbuffer = null, definedCanvas = false) {
|
||
var cmd;
|
||
cmd = BlitScreenQuadCMD._pool.length > 0 ? BlitScreenQuadCMD._pool.pop() : new BlitScreenQuadCMD();
|
||
cmd._source = source;
|
||
cmd._dest = dest;
|
||
cmd._offsetScale = offsetScale;
|
||
cmd._shader = shader;
|
||
cmd._shaderData = shaderData;
|
||
cmd._subShader = subShader;
|
||
cmd._screenType = screenType;
|
||
cmd._commandBuffer = commandbuffer;
|
||
cmd._drawDefineCavans = definedCanvas;
|
||
return cmd;
|
||
}
|
||
run() {
|
||
var source;
|
||
if (!this._source) {
|
||
if (!this._commandBuffer._camera._internalRenderTexture)
|
||
throw "camera internalRenderTexture is null,please set camera enableBuiltInRenderTexture";
|
||
source = this._commandBuffer._camera._internalRenderTexture;
|
||
}
|
||
else
|
||
source = this._source;
|
||
var shader = this._shader || Command._screenShader;
|
||
var shaderData = this._shaderData || Command._screenShaderData;
|
||
var dest = this._dest ? this._dest : (this._drawDefineCavans ? this._dest : this._commandBuffer._camera._internalRenderTexture);
|
||
if (dest) {
|
||
Laya.LayaGL.instance.viewport(0, 0, dest.width, dest.height);
|
||
}
|
||
else {
|
||
let camera = this._commandBuffer._camera;
|
||
let viewport = camera.viewport;
|
||
let vpH = viewport.height;
|
||
let vpY = RenderContext3D.clientHeight - viewport.y - vpH;
|
||
Laya.LayaGL.instance.viewport(viewport.x, vpY, viewport.width, vpH);
|
||
}
|
||
shaderData.setTexture(Command.SCREENTEXTURE_ID, source);
|
||
shaderData.setVector(Command.SCREENTEXTUREOFFSETSCALE_ID, this._offsetScale || BlitScreenQuadCMD._defaultOffsetScale);
|
||
this._sourceTexelSize.setValue(1.0 / source.width, 1.0 / source.height, source.width, source.height);
|
||
shaderData.setVector(Command.MAINTEXTURE_TEXELSIZE_ID, this._sourceTexelSize);
|
||
(RenderTexture.currentActive) && (RenderTexture.currentActive._end());
|
||
(dest) && (dest._start());
|
||
var subShader = shader.getSubShaderAt(this._subShader);
|
||
var passes = subShader._passes;
|
||
for (var i = 0, n = passes.length; i < n; i++) {
|
||
var comDef = BlitScreenQuadCMD._compileDefine;
|
||
shaderData._defineDatas.cloneTo(comDef);
|
||
var shaderPass = passes[i].withCompile(comDef);
|
||
shaderPass.bind();
|
||
shaderPass.uploadUniforms(shaderPass._materialUniformParamsMap, shaderData, true);
|
||
shaderPass.uploadRenderStateBlendDepth(shaderData);
|
||
shaderPass.uploadRenderStateFrontFace(shaderData, false, null);
|
||
switch (this._screenType) {
|
||
case BlitScreenQuadCMD._SCREENTYPE_QUAD:
|
||
RenderContext3D._instance.invertY ? ScreenQuad.instance.renderInvertUV() : ScreenQuad.instance.render();
|
||
break;
|
||
case BlitScreenQuadCMD._SCREENTYPE_TRIANGLE:
|
||
RenderContext3D._instance.invertY ? ScreenTriangle.instance.renderInvertUV() : ScreenTriangle.instance.render();
|
||
break;
|
||
default:
|
||
throw "BlitScreenQuadCMD:unknown screen Type.";
|
||
}
|
||
}
|
||
(dest) && (dest._end());
|
||
}
|
||
recover() {
|
||
BlitScreenQuadCMD._pool.push(this);
|
||
this._source = null;
|
||
this._dest = null;
|
||
this._offsetScale = null;
|
||
this._shader = null;
|
||
this._shaderData = null;
|
||
this._drawDefineCavans = false;
|
||
super.recover();
|
||
}
|
||
}
|
||
BlitScreenQuadCMD._SCREENTYPE_QUAD = 0;
|
||
BlitScreenQuadCMD._SCREENTYPE_TRIANGLE = 1;
|
||
BlitScreenQuadCMD._compileDefine = new DefineDatas();
|
||
BlitScreenQuadCMD._pool = [];
|
||
BlitScreenQuadCMD._defaultOffsetScale = new Vector4(0, 0, 1, 1);
|
||
|
||
class SetRenderTargetCMD extends Command {
|
||
constructor() {
|
||
super(...arguments);
|
||
this._renderTexture = null;
|
||
}
|
||
static create(renderTexture) {
|
||
var cmd;
|
||
cmd = SetRenderTargetCMD._pool.length > 0 ? SetRenderTargetCMD._pool.pop() : new SetRenderTargetCMD();
|
||
cmd._renderTexture = renderTexture;
|
||
return cmd;
|
||
}
|
||
run() {
|
||
(RenderTexture.currentActive) && (RenderTexture.currentActive._end());
|
||
Laya.LayaGL.instance.viewport(0, 0, this._renderTexture.width, this._renderTexture.height);
|
||
this._renderTexture._start();
|
||
}
|
||
recover() {
|
||
SetRenderTargetCMD._pool.push(this);
|
||
this._renderTexture = null;
|
||
}
|
||
}
|
||
SetRenderTargetCMD._pool = [];
|
||
|
||
(function (ShaderDataType) {
|
||
ShaderDataType[ShaderDataType["Int"] = 0] = "Int";
|
||
ShaderDataType[ShaderDataType["Bool"] = 1] = "Bool";
|
||
ShaderDataType[ShaderDataType["Number"] = 2] = "Number";
|
||
ShaderDataType[ShaderDataType["Vector2"] = 3] = "Vector2";
|
||
ShaderDataType[ShaderDataType["Vector3"] = 4] = "Vector3";
|
||
ShaderDataType[ShaderDataType["Vector4"] = 5] = "Vector4";
|
||
ShaderDataType[ShaderDataType["Quaternion"] = 6] = "Quaternion";
|
||
ShaderDataType[ShaderDataType["Matrix4x4"] = 7] = "Matrix4x4";
|
||
ShaderDataType[ShaderDataType["Buffer"] = 8] = "Buffer";
|
||
ShaderDataType[ShaderDataType["Texture"] = 9] = "Texture";
|
||
})(exports.ShaderDataType || (exports.ShaderDataType = {}));
|
||
class SetShaderDataCMD extends Command {
|
||
constructor() {
|
||
super(...arguments);
|
||
this._shaderData = null;
|
||
this._nameID = 0;
|
||
this._value = null;
|
||
this._dataType = -1;
|
||
}
|
||
static create(shaderData, nameID, value, shaderDataType, commandBuffer) {
|
||
var cmd;
|
||
cmd = SetShaderDataCMD._pool.length > 0 ? SetShaderDataCMD._pool.pop() : new SetShaderDataCMD();
|
||
cmd._shaderData = shaderData;
|
||
cmd._nameID = nameID;
|
||
cmd._value = value;
|
||
cmd._dataType = shaderDataType;
|
||
cmd._commandBuffer = commandBuffer;
|
||
return cmd;
|
||
}
|
||
run() {
|
||
switch (this._dataType) {
|
||
case exports.ShaderDataType.Int:
|
||
this._shaderData.setInt(this._nameID, this._value);
|
||
break;
|
||
case exports.ShaderDataType.Number:
|
||
this._shaderData.setNumber(this._nameID, this._value);
|
||
break;
|
||
case exports.ShaderDataType.Bool:
|
||
this._shaderData.setBool(this._nameID, this._value);
|
||
break;
|
||
case exports.ShaderDataType.Matrix4x4:
|
||
this._shaderData.setMatrix4x4(this._nameID, this._value);
|
||
break;
|
||
case exports.ShaderDataType.Quaternion:
|
||
this._shaderData.setQuaternion(this._nameID, this._value);
|
||
break;
|
||
case exports.ShaderDataType.Texture:
|
||
this._shaderData.setTexture(this._nameID, this._value);
|
||
break;
|
||
case exports.ShaderDataType.Vector4:
|
||
this._shaderData.setVector(this._nameID, this._value);
|
||
break;
|
||
case exports.ShaderDataType.Vector2:
|
||
this._shaderData.setVector2(this._nameID, this._value);
|
||
break;
|
||
case exports.ShaderDataType.Vector3:
|
||
this._shaderData.setVector3(this._nameID, this._value);
|
||
break;
|
||
case exports.ShaderDataType.Buffer:
|
||
this._shaderData.setBuffer(this._nameID, this._value);
|
||
break;
|
||
default:
|
||
throw "no type shaderValue on this CommendBuffer";
|
||
}
|
||
}
|
||
recover() {
|
||
SetShaderDataCMD._pool.push(this);
|
||
this._shaderData = null;
|
||
this._nameID = 0;
|
||
this._value = null;
|
||
this._dataType = -1;
|
||
}
|
||
}
|
||
SetShaderDataCMD._pool = [];
|
||
|
||
class Transform3D extends Laya.EventDispatcher {
|
||
constructor(owner) {
|
||
super();
|
||
this._localPosition = new Vector3(0, 0, 0);
|
||
this._localRotation = new Quaternion(0, 0, 0, 1);
|
||
this._localScale = new Vector3(1, 1, 1);
|
||
this._localRotationEuler = new Vector3(0, 0, 0);
|
||
this._localMatrix = new Matrix4x4();
|
||
this._position = new Vector3(0, 0, 0);
|
||
this._rotation = new Quaternion(0, 0, 0, 1);
|
||
this._scale = new Vector3(1, 1, 1);
|
||
this._rotationEuler = new Vector3(0, 0, 0);
|
||
this._worldMatrix = new Matrix4x4();
|
||
this._children = null;
|
||
this._parent = null;
|
||
this._dummy = null;
|
||
this._transformFlag = 0;
|
||
this._owner = owner;
|
||
this._children = [];
|
||
this._setTransformFlag(Transform3D.TRANSFORM_LOCALQUATERNION | Transform3D.TRANSFORM_LOCALEULER | Transform3D.TRANSFORM_LOCALMATRIX, false);
|
||
this._setTransformFlag(Transform3D.TRANSFORM_WORLDPOSITION | Transform3D.TRANSFORM_WORLDQUATERNION | Transform3D.TRANSFORM_WORLDEULER | Transform3D.TRANSFORM_WORLDSCALE | Transform3D.TRANSFORM_WORLDMATRIX, true);
|
||
}
|
||
get _isFrontFaceInvert() {
|
||
var scale = this.getWorldLossyScale();
|
||
var isInvert = scale.x < 0;
|
||
(scale.y < 0) && (isInvert = !isInvert);
|
||
(scale.z < 0) && (isInvert = !isInvert);
|
||
return isInvert;
|
||
}
|
||
get owner() {
|
||
return this._owner;
|
||
}
|
||
get worldNeedUpdate() {
|
||
return this._getTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX);
|
||
}
|
||
get localPositionX() {
|
||
return this._localPosition.x;
|
||
}
|
||
set localPositionX(x) {
|
||
this._localPosition.x = x;
|
||
this.localPosition = this._localPosition;
|
||
}
|
||
get localPositionY() {
|
||
return this._localPosition.y;
|
||
}
|
||
set localPositionY(y) {
|
||
this._localPosition.y = y;
|
||
this.localPosition = this._localPosition;
|
||
}
|
||
get localPositionZ() {
|
||
return this._localPosition.z;
|
||
}
|
||
set localPositionZ(z) {
|
||
this._localPosition.z = z;
|
||
this.localPosition = this._localPosition;
|
||
}
|
||
get localPosition() {
|
||
return this._localPosition;
|
||
}
|
||
set localPosition(value) {
|
||
if (this._localPosition !== value)
|
||
value.cloneTo(this._localPosition);
|
||
this._setTransformFlag(Transform3D.TRANSFORM_LOCALMATRIX, true);
|
||
this._onWorldPositionTransform();
|
||
}
|
||
get localRotationX() {
|
||
return this.localRotation.x;
|
||
}
|
||
set localRotationX(x) {
|
||
this._localRotation.x = x;
|
||
this.localRotation = this._localRotation;
|
||
}
|
||
get localRotationY() {
|
||
return this.localRotation.y;
|
||
}
|
||
set localRotationY(y) {
|
||
this._localRotation.y = y;
|
||
this.localRotation = this._localRotation;
|
||
}
|
||
get localRotationZ() {
|
||
return this.localRotation.z;
|
||
}
|
||
set localRotationZ(z) {
|
||
this._localRotation.z = z;
|
||
this.localRotation = this._localRotation;
|
||
}
|
||
get localRotationW() {
|
||
return this.localRotation.w;
|
||
}
|
||
set localRotationW(w) {
|
||
this._localRotation.w = w;
|
||
this.localRotation = this._localRotation;
|
||
}
|
||
get localRotation() {
|
||
if (this._getTransformFlag(Transform3D.TRANSFORM_LOCALQUATERNION)) {
|
||
var eulerE = this._localRotationEuler;
|
||
Quaternion.createFromYawPitchRoll(eulerE.y / Transform3D._angleToRandin, eulerE.x / Transform3D._angleToRandin, eulerE.z / Transform3D._angleToRandin, this._localRotation);
|
||
this._setTransformFlag(Transform3D.TRANSFORM_LOCALQUATERNION, false);
|
||
}
|
||
return this._localRotation;
|
||
}
|
||
set localRotation(value) {
|
||
if (this._localRotation !== value)
|
||
value.cloneTo(this._localRotation);
|
||
this._localRotation.normalize(this._localRotation);
|
||
this._setTransformFlag(Transform3D.TRANSFORM_LOCALEULER | Transform3D.TRANSFORM_LOCALMATRIX, true);
|
||
this._setTransformFlag(Transform3D.TRANSFORM_LOCALQUATERNION, false);
|
||
this._onWorldRotationTransform();
|
||
}
|
||
get localScaleX() {
|
||
return this._localScale.x;
|
||
}
|
||
set localScaleX(value) {
|
||
this._localScale.x = value;
|
||
this.localScale = this._localScale;
|
||
}
|
||
get localScaleY() {
|
||
return this._localScale.y;
|
||
}
|
||
set localScaleY(value) {
|
||
this._localScale.y = value;
|
||
this.localScale = this._localScale;
|
||
}
|
||
get localScaleZ() {
|
||
return this._localScale.z;
|
||
}
|
||
set localScaleZ(value) {
|
||
this._localScale.z = value;
|
||
this.localScale = this._localScale;
|
||
}
|
||
get localScale() {
|
||
return this._localScale;
|
||
}
|
||
set localScale(value) {
|
||
if (this._localScale !== value)
|
||
value.cloneTo(this._localScale);
|
||
this._setTransformFlag(Transform3D.TRANSFORM_LOCALMATRIX, true);
|
||
this._onWorldScaleTransform();
|
||
}
|
||
get localRotationEulerX() {
|
||
return this.localRotationEuler.x;
|
||
}
|
||
set localRotationEulerX(value) {
|
||
this._localRotationEuler.x = value;
|
||
this.localRotationEuler = this._localRotationEuler;
|
||
}
|
||
get localRotationEulerY() {
|
||
return this.localRotationEuler.y;
|
||
}
|
||
set localRotationEulerY(value) {
|
||
this._localRotationEuler.y = value;
|
||
this.localRotationEuler = this._localRotationEuler;
|
||
}
|
||
get localRotationEulerZ() {
|
||
return this.localRotationEuler.z;
|
||
}
|
||
set localRotationEulerZ(value) {
|
||
this._localRotationEuler.z = value;
|
||
this.localRotationEuler = this._localRotationEuler;
|
||
}
|
||
get localRotationEuler() {
|
||
if (this._getTransformFlag(Transform3D.TRANSFORM_LOCALEULER)) {
|
||
this._localRotation.getYawPitchRoll(Transform3D._tempVector30);
|
||
var euler = Transform3D._tempVector30;
|
||
var localRotationEuler = this._localRotationEuler;
|
||
localRotationEuler.x = euler.y * Transform3D._angleToRandin;
|
||
localRotationEuler.y = euler.x * Transform3D._angleToRandin;
|
||
localRotationEuler.z = euler.z * Transform3D._angleToRandin;
|
||
this._setTransformFlag(Transform3D.TRANSFORM_LOCALEULER, false);
|
||
}
|
||
return this._localRotationEuler;
|
||
}
|
||
set localRotationEuler(value) {
|
||
if (this._localRotationEuler !== value)
|
||
value.cloneTo(this._localRotationEuler);
|
||
this._setTransformFlag(Transform3D.TRANSFORM_LOCALEULER, false);
|
||
this._setTransformFlag(Transform3D.TRANSFORM_LOCALQUATERNION | Transform3D.TRANSFORM_LOCALMATRIX, true);
|
||
this._onWorldRotationTransform();
|
||
}
|
||
get localMatrix() {
|
||
if (this._getTransformFlag(Transform3D.TRANSFORM_LOCALMATRIX)) {
|
||
Matrix4x4.createAffineTransformation(this._localPosition, this.localRotation, this._localScale, this._localMatrix);
|
||
this._setTransformFlag(Transform3D.TRANSFORM_LOCALMATRIX, false);
|
||
}
|
||
return this._localMatrix;
|
||
}
|
||
set localMatrix(value) {
|
||
if (this._localMatrix !== value)
|
||
value.cloneTo(this._localMatrix);
|
||
this._localMatrix.decomposeTransRotScale(this._localPosition, this._localRotation, this._localScale);
|
||
this._setTransformFlag(Transform3D.TRANSFORM_LOCALEULER, true);
|
||
this._setTransformFlag(Transform3D.TRANSFORM_LOCALMATRIX, false);
|
||
this._onWorldTransform();
|
||
}
|
||
get position() {
|
||
if (this._getTransformFlag(Transform3D.TRANSFORM_WORLDPOSITION)) {
|
||
if (this._parent != null) {
|
||
var worldMatE = this.worldMatrix.elements;
|
||
this._position.x = worldMatE[12];
|
||
this._position.y = worldMatE[13];
|
||
this._position.z = worldMatE[14];
|
||
}
|
||
else {
|
||
this._localPosition.cloneTo(this._position);
|
||
}
|
||
this._setTransformFlag(Transform3D.TRANSFORM_WORLDPOSITION, false);
|
||
}
|
||
return this._position;
|
||
}
|
||
set position(value) {
|
||
if (this._parent != null) {
|
||
var parentInvMat = Transform3D._tempMatrix0;
|
||
this._parent.worldMatrix.invert(parentInvMat);
|
||
Vector3.transformCoordinate(value, parentInvMat, this._localPosition);
|
||
}
|
||
else {
|
||
value.cloneTo(this._localPosition);
|
||
}
|
||
this.localPosition = this._localPosition;
|
||
if (this._position !== value)
|
||
value.cloneTo(this._position);
|
||
this._setTransformFlag(Transform3D.TRANSFORM_WORLDPOSITION, false);
|
||
}
|
||
get rotation() {
|
||
if (this._getTransformFlag(Transform3D.TRANSFORM_WORLDQUATERNION)) {
|
||
if (this._parent != null)
|
||
Quaternion.multiply(this._parent.rotation, this.localRotation, this._rotation);
|
||
else
|
||
this.localRotation.cloneTo(this._rotation);
|
||
this._setTransformFlag(Transform3D.TRANSFORM_WORLDQUATERNION, false);
|
||
}
|
||
return this._rotation;
|
||
}
|
||
set rotation(value) {
|
||
if (this._parent != null) {
|
||
this._parent.rotation.invert(Transform3D._tempQuaternion0);
|
||
Quaternion.multiply(Transform3D._tempQuaternion0, value, this._localRotation);
|
||
}
|
||
else {
|
||
value.cloneTo(this._localRotation);
|
||
}
|
||
this.localRotation = this._localRotation;
|
||
if (value !== this._rotation)
|
||
value.cloneTo(this._rotation);
|
||
this._setTransformFlag(Transform3D.TRANSFORM_WORLDQUATERNION, false);
|
||
}
|
||
get rotationEuler() {
|
||
if (this._getTransformFlag(Transform3D.TRANSFORM_WORLDEULER)) {
|
||
this.rotation.getYawPitchRoll(Transform3D._tempVector30);
|
||
var eulerE = Transform3D._tempVector30;
|
||
var rotationEulerE = this._rotationEuler;
|
||
rotationEulerE.x = eulerE.y * Transform3D._angleToRandin;
|
||
rotationEulerE.y = eulerE.x * Transform3D._angleToRandin;
|
||
rotationEulerE.z = eulerE.z * Transform3D._angleToRandin;
|
||
this._setTransformFlag(Transform3D.TRANSFORM_WORLDEULER, false);
|
||
}
|
||
return this._rotationEuler;
|
||
}
|
||
set rotationEuler(value) {
|
||
Quaternion.createFromYawPitchRoll(value.y / Transform3D._angleToRandin, value.x / Transform3D._angleToRandin, value.z / Transform3D._angleToRandin, this._rotation);
|
||
this.rotation = this._rotation;
|
||
if (this._rotationEuler !== value)
|
||
value.cloneTo(this._rotationEuler);
|
||
this._setTransformFlag(Transform3D.TRANSFORM_WORLDEULER, false);
|
||
}
|
||
get worldMatrix() {
|
||
if (this._getTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX)) {
|
||
if (this._parent != null)
|
||
Matrix4x4.multiply(this._parent.worldMatrix, this.localMatrix, this._worldMatrix);
|
||
else
|
||
this.localMatrix.cloneTo(this._worldMatrix);
|
||
this._setTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX, false);
|
||
}
|
||
return this._worldMatrix;
|
||
}
|
||
set worldMatrix(value) {
|
||
if (this._parent === null) {
|
||
value.cloneTo(this._localMatrix);
|
||
}
|
||
else {
|
||
this._parent.worldMatrix.invert(this._localMatrix);
|
||
Matrix4x4.multiply(this._localMatrix, value, this._localMatrix);
|
||
}
|
||
this.localMatrix = this._localMatrix;
|
||
if (this._worldMatrix !== value)
|
||
value.cloneTo(this._worldMatrix);
|
||
this._setTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX, false);
|
||
}
|
||
_getScaleMatrix() {
|
||
var invRotation = Transform3D._tempQuaternion0;
|
||
var invRotationMat = Transform3D._tempMatrix3x30;
|
||
var worldRotScaMat = Transform3D._tempMatrix3x31;
|
||
var scaMat = Transform3D._tempMatrix3x32;
|
||
Matrix3x3.createFromMatrix4x4(this.worldMatrix, worldRotScaMat);
|
||
this.rotation.invert(invRotation);
|
||
Matrix3x3.createRotationQuaternion(invRotation, invRotationMat);
|
||
Matrix3x3.multiply(invRotationMat, worldRotScaMat, scaMat);
|
||
return scaMat;
|
||
}
|
||
_setTransformFlag(type, value) {
|
||
if (value)
|
||
this._transformFlag |= type;
|
||
else
|
||
this._transformFlag &= ~type;
|
||
}
|
||
_getTransformFlag(type) {
|
||
return (this._transformFlag & type) != 0;
|
||
}
|
||
_setParent(value) {
|
||
if (this._parent !== value) {
|
||
if (this._parent) {
|
||
var parentChilds = this._parent._children;
|
||
var index = parentChilds.indexOf(this);
|
||
parentChilds.splice(index, 1);
|
||
}
|
||
if (value) {
|
||
value._children.push(this);
|
||
(value) && (this._onWorldTransform());
|
||
}
|
||
this._parent = value;
|
||
}
|
||
}
|
||
_onWorldPositionRotationTransform() {
|
||
if (!this._getTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX) || !this._getTransformFlag(Transform3D.TRANSFORM_WORLDPOSITION) || !this._getTransformFlag(Transform3D.TRANSFORM_WORLDQUATERNION) || !this._getTransformFlag(Transform3D.TRANSFORM_WORLDEULER)) {
|
||
this._setTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX | Transform3D.TRANSFORM_WORLDPOSITION | Transform3D.TRANSFORM_WORLDQUATERNION | Transform3D.TRANSFORM_WORLDEULER, true);
|
||
this.event(Laya.Event.TRANSFORM_CHANGED, this._transformFlag);
|
||
}
|
||
for (var i = 0, n = this._children.length; i < n; i++)
|
||
this._children[i]._onWorldPositionRotationTransform();
|
||
}
|
||
_onWorldPositionScaleTransform() {
|
||
if (!this._getTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX) || !this._getTransformFlag(Transform3D.TRANSFORM_WORLDPOSITION) || !this._getTransformFlag(Transform3D.TRANSFORM_WORLDSCALE)) {
|
||
this._setTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX | Transform3D.TRANSFORM_WORLDPOSITION | Transform3D.TRANSFORM_WORLDSCALE, true);
|
||
this.event(Laya.Event.TRANSFORM_CHANGED, this._transformFlag);
|
||
}
|
||
for (var i = 0, n = this._children.length; i < n; i++)
|
||
this._children[i]._onWorldPositionScaleTransform();
|
||
}
|
||
_onWorldPositionTransform() {
|
||
if (!this._getTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX) || !this._getTransformFlag(Transform3D.TRANSFORM_WORLDPOSITION)) {
|
||
this._setTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX | Transform3D.TRANSFORM_WORLDPOSITION, true);
|
||
this.event(Laya.Event.TRANSFORM_CHANGED, this._transformFlag);
|
||
}
|
||
for (var i = 0, n = this._children.length; i < n; i++)
|
||
this._children[i]._onWorldPositionTransform();
|
||
}
|
||
_onWorldRotationTransform() {
|
||
if (!this._getTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX) || !this._getTransformFlag(Transform3D.TRANSFORM_WORLDQUATERNION) || !this._getTransformFlag(Transform3D.TRANSFORM_WORLDEULER)) {
|
||
this._setTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX | Transform3D.TRANSFORM_WORLDQUATERNION | Transform3D.TRANSFORM_WORLDEULER, true);
|
||
this.event(Laya.Event.TRANSFORM_CHANGED, this._transformFlag);
|
||
}
|
||
for (var i = 0, n = this._children.length; i < n; i++)
|
||
this._children[i]._onWorldPositionRotationTransform();
|
||
}
|
||
_onWorldScaleTransform() {
|
||
if (!this._getTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX) || !this._getTransformFlag(Transform3D.TRANSFORM_WORLDSCALE)) {
|
||
this._setTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX | Transform3D.TRANSFORM_WORLDSCALE, true);
|
||
this.event(Laya.Event.TRANSFORM_CHANGED, this._transformFlag);
|
||
}
|
||
for (var i = 0, n = this._children.length; i < n; i++)
|
||
this._children[i]._onWorldPositionScaleTransform();
|
||
}
|
||
_onWorldTransform() {
|
||
if (!this._getTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX) || !this._getTransformFlag(Transform3D.TRANSFORM_WORLDPOSITION) || !this._getTransformFlag(Transform3D.TRANSFORM_WORLDQUATERNION) || !this._getTransformFlag(Transform3D.TRANSFORM_WORLDEULER) || !this._getTransformFlag(Transform3D.TRANSFORM_WORLDSCALE)) {
|
||
this._setTransformFlag(Transform3D.TRANSFORM_WORLDMATRIX | Transform3D.TRANSFORM_WORLDPOSITION | Transform3D.TRANSFORM_WORLDQUATERNION | Transform3D.TRANSFORM_WORLDEULER | Transform3D.TRANSFORM_WORLDSCALE, true);
|
||
this.event(Laya.Event.TRANSFORM_CHANGED, this._transformFlag);
|
||
}
|
||
for (var i = 0, n = this._children.length; i < n; i++)
|
||
this._children[i]._onWorldTransform();
|
||
}
|
||
translate(translation, isLocal = true) {
|
||
if (isLocal) {
|
||
Matrix4x4.createFromQuaternion(this.localRotation, Transform3D._tempMatrix0);
|
||
Vector3.transformCoordinate(translation, Transform3D._tempMatrix0, Transform3D._tempVector30);
|
||
Vector3.add(this.localPosition, Transform3D._tempVector30, this._localPosition);
|
||
this.localPosition = this._localPosition;
|
||
}
|
||
else {
|
||
Vector3.add(this.position, translation, this._position);
|
||
this.position = this._position;
|
||
}
|
||
}
|
||
rotate(rotation, isLocal = true, isRadian = true) {
|
||
var rot;
|
||
if (isRadian) {
|
||
rot = rotation;
|
||
}
|
||
else {
|
||
Vector3.scale(rotation, Math.PI / 180.0, Transform3D._tempVector30);
|
||
rot = Transform3D._tempVector30;
|
||
}
|
||
Quaternion.createFromYawPitchRoll(rot.y, rot.x, rot.z, Transform3D._tempQuaternion0);
|
||
if (isLocal) {
|
||
Quaternion.multiply(this._localRotation, Transform3D._tempQuaternion0, this._localRotation);
|
||
this.localRotation = this._localRotation;
|
||
}
|
||
else {
|
||
Quaternion.multiply(Transform3D._tempQuaternion0, this.rotation, this._rotation);
|
||
this.rotation = this._rotation;
|
||
}
|
||
}
|
||
getForward(forward) {
|
||
var worldMatElem = this.worldMatrix.elements;
|
||
forward.x = -worldMatElem[8];
|
||
forward.y = -worldMatElem[9];
|
||
forward.z = -worldMatElem[10];
|
||
}
|
||
getUp(up) {
|
||
var worldMatElem = this.worldMatrix.elements;
|
||
up.x = worldMatElem[4];
|
||
up.y = worldMatElem[5];
|
||
up.z = worldMatElem[6];
|
||
}
|
||
getRight(right) {
|
||
var worldMatElem = this.worldMatrix.elements;
|
||
right.x = worldMatElem[0];
|
||
right.y = worldMatElem[1];
|
||
right.z = worldMatElem[2];
|
||
}
|
||
lookAt(target, up, isLocal = false) {
|
||
var eye;
|
||
if (isLocal) {
|
||
eye = this._localPosition;
|
||
if (Math.abs(eye.x - target.x) < MathUtils3D.zeroTolerance && Math.abs(eye.y - target.y) < MathUtils3D.zeroTolerance && Math.abs(eye.z - target.z) < MathUtils3D.zeroTolerance)
|
||
return;
|
||
Quaternion.lookAt(this._localPosition, target, up, this._localRotation);
|
||
this._localRotation.invert(this._localRotation);
|
||
this.localRotation = this._localRotation;
|
||
}
|
||
else {
|
||
var worldPosition = this.position;
|
||
eye = worldPosition;
|
||
if (Math.abs(eye.x - target.x) < MathUtils3D.zeroTolerance && Math.abs(eye.y - target.y) < MathUtils3D.zeroTolerance && Math.abs(eye.z - target.z) < MathUtils3D.zeroTolerance)
|
||
return;
|
||
Quaternion.lookAt(worldPosition, target, up, this._rotation);
|
||
this._rotation.invert(this._rotation);
|
||
this.rotation = this._rotation;
|
||
}
|
||
}
|
||
getWorldLossyScale() {
|
||
if (this._getTransformFlag(Transform3D.TRANSFORM_WORLDSCALE)) {
|
||
if (this._parent !== null) {
|
||
var scaMatE = this._getScaleMatrix().elements;
|
||
this._scale.x = scaMatE[0];
|
||
this._scale.y = scaMatE[4];
|
||
this._scale.z = scaMatE[8];
|
||
}
|
||
else {
|
||
this._localScale.cloneTo(this._scale);
|
||
}
|
||
this._setTransformFlag(Transform3D.TRANSFORM_WORLDSCALE, false);
|
||
}
|
||
return this._scale;
|
||
}
|
||
setWorldLossyScale(value) {
|
||
if (this._parent !== null) {
|
||
var scaleMat = Transform3D._tempMatrix3x33;
|
||
var localScaleMat = Transform3D._tempMatrix3x33;
|
||
var localScaleMatE = localScaleMat.elements;
|
||
var parInvScaleMat = this._parent._getScaleMatrix();
|
||
parInvScaleMat.invert(parInvScaleMat);
|
||
Matrix3x3.createFromScaling(value, scaleMat);
|
||
Matrix3x3.multiply(parInvScaleMat, scaleMat, localScaleMat);
|
||
this._localScale.x = localScaleMatE[0];
|
||
this._localScale.y = localScaleMatE[4];
|
||
this._localScale.z = localScaleMatE[8];
|
||
}
|
||
else {
|
||
value.cloneTo(this._localScale);
|
||
}
|
||
this.localScale = this._localScale;
|
||
if (this._scale !== value)
|
||
value.cloneTo(this._scale);
|
||
this._setTransformFlag(Transform3D.TRANSFORM_WORLDSCALE, false);
|
||
}
|
||
get scale() {
|
||
console.warn("Transfrm3D: discard function,please use getWorldLossyScale instead.");
|
||
return this.getWorldLossyScale();
|
||
}
|
||
set scale(value) {
|
||
console.warn("Transfrm3D: discard function,please use setWorldLossyScale instead.");
|
||
this.setWorldLossyScale(value);
|
||
}
|
||
}
|
||
Transform3D._tempVector30 = new Vector3();
|
||
Transform3D._tempQuaternion0 = new Quaternion();
|
||
Transform3D._tempMatrix0 = new Matrix4x4();
|
||
Transform3D._tempMatrix3x30 = new Matrix3x3();
|
||
Transform3D._tempMatrix3x31 = new Matrix3x3();
|
||
Transform3D._tempMatrix3x32 = new Matrix3x3();
|
||
Transform3D._tempMatrix3x33 = new Matrix3x3();
|
||
Transform3D.TRANSFORM_LOCALQUATERNION = 0x01;
|
||
Transform3D.TRANSFORM_LOCALEULER = 0x02;
|
||
Transform3D.TRANSFORM_LOCALMATRIX = 0x04;
|
||
Transform3D.TRANSFORM_WORLDPOSITION = 0x08;
|
||
Transform3D.TRANSFORM_WORLDQUATERNION = 0x10;
|
||
Transform3D.TRANSFORM_WORLDSCALE = 0x20;
|
||
Transform3D.TRANSFORM_WORLDMATRIX = 0x40;
|
||
Transform3D.TRANSFORM_WORLDEULER = 0x80;
|
||
Transform3D._angleToRandin = 180 / Math.PI;
|
||
|
||
class Sprite3D extends Laya.Node {
|
||
constructor(name = null, isStatic = false) {
|
||
super();
|
||
this._needProcessCollisions = false;
|
||
this._needProcessTriggers = false;
|
||
this._id = ++Sprite3D._uniqueIDCounter;
|
||
this._transform = new Transform3D(this);
|
||
this._isStatic = isStatic;
|
||
this.layer = 0;
|
||
this.name = name ? name : "New Sprite3D";
|
||
}
|
||
static __init__() {
|
||
}
|
||
static instantiate(original, parent = null, worldPositionStays = true, position = null, rotation = null) {
|
||
var destSprite3D = original.clone();
|
||
(parent) && (parent.addChild(destSprite3D));
|
||
var transform = destSprite3D.transform;
|
||
if (worldPositionStays) {
|
||
var worldMatrix = transform.worldMatrix;
|
||
original.transform.worldMatrix.cloneTo(worldMatrix);
|
||
transform.worldMatrix = worldMatrix;
|
||
}
|
||
else {
|
||
(position) && (transform.position = position);
|
||
(rotation) && (transform.rotation = rotation);
|
||
}
|
||
return destSprite3D;
|
||
}
|
||
static load(url, complete) {
|
||
Laya.Laya.loader.create(url, complete, null, Sprite3D.HIERARCHY);
|
||
}
|
||
get id() {
|
||
return this._id;
|
||
}
|
||
get layer() {
|
||
return this._layer;
|
||
}
|
||
set layer(value) {
|
||
if (this._layer !== value) {
|
||
if (value >= 0 && value <= 30) {
|
||
this._layer = value;
|
||
}
|
||
else {
|
||
throw new Error("Layer value must be 0-30.");
|
||
}
|
||
}
|
||
}
|
||
get url() {
|
||
return this._url;
|
||
}
|
||
get isStatic() {
|
||
return this._isStatic;
|
||
}
|
||
get transform() {
|
||
return this._transform;
|
||
}
|
||
_setCreateURL(url) {
|
||
this._url = Laya.URL.formatURL(url);
|
||
}
|
||
_changeAnimatorsToLinkSprite3D(sprite3D, isLink, path) {
|
||
var animator = this.getComponent(Animator);
|
||
if (animator) {
|
||
if (!animator.avatar)
|
||
sprite3D._changeAnimatorToLinkSprite3DNoAvatar(animator, isLink, path);
|
||
}
|
||
if (this._parent && this._parent instanceof Sprite3D) {
|
||
path.unshift(this._parent.name);
|
||
var p = this._parent;
|
||
(p._hierarchyAnimator) && (p._changeAnimatorsToLinkSprite3D(sprite3D, isLink, path));
|
||
}
|
||
}
|
||
_setHierarchyAnimator(animator, parentAnimator) {
|
||
this._changeHierarchyAnimator(animator);
|
||
this._changeAnimatorAvatar(animator.avatar);
|
||
for (var i = 0, n = this._children.length; i < n; i++) {
|
||
var child = this._children[i];
|
||
(child._hierarchyAnimator == parentAnimator) && (child._setHierarchyAnimator(animator, parentAnimator));
|
||
}
|
||
}
|
||
_clearHierarchyAnimator(animator, parentAnimator) {
|
||
this._changeHierarchyAnimator(parentAnimator);
|
||
this._changeAnimatorAvatar(parentAnimator ? parentAnimator.avatar : null);
|
||
for (var i = 0, n = this._children.length; i < n; i++) {
|
||
var child = this._children[i];
|
||
(child._hierarchyAnimator == animator) && (child._clearHierarchyAnimator(animator, parentAnimator));
|
||
}
|
||
}
|
||
_changeHierarchyAnimatorAvatar(animator, avatar) {
|
||
this._changeAnimatorAvatar(avatar);
|
||
for (var i = 0, n = this._children.length; i < n; i++) {
|
||
var child = this._children[i];
|
||
(child._hierarchyAnimator == animator) && (child._changeHierarchyAnimatorAvatar(animator, avatar));
|
||
}
|
||
}
|
||
_changeAnimatorToLinkSprite3DNoAvatar(animator, isLink, path) {
|
||
animator._handleSpriteOwnersBySprite(isLink, path, this);
|
||
for (var i = 0, n = this._children.length; i < n; i++) {
|
||
var child = this._children[i];
|
||
var index = path.length;
|
||
path.push(child.name);
|
||
child._changeAnimatorToLinkSprite3DNoAvatar(animator, isLink, path);
|
||
path.splice(index, 1);
|
||
}
|
||
}
|
||
_changeHierarchyAnimator(animator) {
|
||
this._hierarchyAnimator = animator;
|
||
}
|
||
_changeAnimatorAvatar(avatar) {
|
||
}
|
||
_onInActiveInScene() {
|
||
super._onInActiveInScene();
|
||
if (!this._scripts)
|
||
return;
|
||
for (let i = 0, n = this._scripts.length; i < n; i++)
|
||
this.scene._removeScript(this._scripts[i]);
|
||
}
|
||
_onAdded() {
|
||
if (this._parent instanceof Sprite3D) {
|
||
var parent3D = this._parent;
|
||
this.transform._setParent(parent3D.transform);
|
||
if (parent3D._hierarchyAnimator) {
|
||
(!this._hierarchyAnimator) && (this._setHierarchyAnimator(parent3D._hierarchyAnimator, null));
|
||
parent3D._changeAnimatorsToLinkSprite3D(this, true, [this.name]);
|
||
}
|
||
}
|
||
super._onAdded();
|
||
}
|
||
_onRemoved() {
|
||
super._onRemoved();
|
||
if (this._parent instanceof Sprite3D) {
|
||
var parent3D = this._parent;
|
||
this.transform._setParent(null);
|
||
if (parent3D._hierarchyAnimator) {
|
||
(this._hierarchyAnimator == parent3D._hierarchyAnimator) && (this._clearHierarchyAnimator(parent3D._hierarchyAnimator, null));
|
||
parent3D._changeAnimatorsToLinkSprite3D(this, false, [this.name]);
|
||
}
|
||
}
|
||
}
|
||
_parse(data, spriteMap) {
|
||
(data.isStatic !== undefined) && (this._isStatic = data.isStatic);
|
||
(data.active !== undefined) && (this.active = data.active);
|
||
(data.name != undefined) && (this.name = data.name);
|
||
if (data.position !== undefined) {
|
||
var loccalPosition = this.transform.localPosition;
|
||
loccalPosition.fromArray(data.position);
|
||
this.transform.localPosition = loccalPosition;
|
||
}
|
||
if (data.rotationEuler !== undefined) {
|
||
var localRotationEuler = this.transform.localRotationEuler;
|
||
localRotationEuler.fromArray(data.rotationEuler);
|
||
this.transform.localRotationEuler = localRotationEuler;
|
||
}
|
||
if (data.rotation !== undefined) {
|
||
var localRotation = this.transform.localRotation;
|
||
localRotation.fromArray(data.rotation);
|
||
this.transform.localRotation = localRotation;
|
||
}
|
||
if (data.scale !== undefined) {
|
||
var localScale = this.transform.localScale;
|
||
localScale.fromArray(data.scale);
|
||
this.transform.localScale = localScale;
|
||
}
|
||
(data.layer != undefined) && (this.layer = data.layer);
|
||
}
|
||
_cloneTo(destObject, srcRoot, dstRoot) {
|
||
if (this.destroyed)
|
||
throw new Error("Sprite3D: Can't be cloned if the Sprite3D has destroyed.");
|
||
var destSprite3D = destObject;
|
||
var trans = this._transform;
|
||
var destTrans = destSprite3D._transform;
|
||
destSprite3D.name = this.name;
|
||
destSprite3D.destroyed = this.destroyed;
|
||
destSprite3D.active = this.active;
|
||
destTrans.localPosition = trans.localPosition;
|
||
destTrans.localRotation = trans.localRotation;
|
||
destTrans.localScale = trans.localScale;
|
||
destSprite3D._isStatic = this._isStatic;
|
||
destSprite3D.layer = this.layer;
|
||
super._cloneTo(destSprite3D, srcRoot, dstRoot);
|
||
}
|
||
static _createSprite3DInstance(scrSprite) {
|
||
var node = scrSprite._create();
|
||
var children = scrSprite._children;
|
||
for (var i = 0, n = children.length; i < n; i++) {
|
||
var child = Sprite3D._createSprite3DInstance(children[i]);
|
||
node.addChild(child);
|
||
}
|
||
return node;
|
||
}
|
||
static _parseSprite3DInstance(srcRoot, dstRoot, scrSprite, dstSprite) {
|
||
var srcChildren = scrSprite._children;
|
||
var dstChildren = dstSprite._children;
|
||
for (var i = 0, n = srcChildren.length; i < n; i++)
|
||
Sprite3D._parseSprite3DInstance(srcRoot, dstRoot, srcChildren[i], dstChildren[i]);
|
||
scrSprite._cloneTo(dstSprite, srcRoot, dstRoot);
|
||
}
|
||
clone() {
|
||
var dstSprite3D = Sprite3D._createSprite3DInstance(this);
|
||
Sprite3D._parseSprite3DInstance(this, dstSprite3D, this, dstSprite3D);
|
||
return dstSprite3D;
|
||
}
|
||
destroy(destroyChild = true) {
|
||
if (this.destroyed)
|
||
return;
|
||
super.destroy(destroyChild);
|
||
this._transform = null;
|
||
this._scripts = null;
|
||
this._url && Laya.Loader.clearRes(this._url);
|
||
}
|
||
_create() {
|
||
return new Sprite3D();
|
||
}
|
||
}
|
||
Sprite3D.HIERARCHY = "HIERARCHY";
|
||
Sprite3D.WORLDMATRIX = Shader3D.propertyNameToID("u_WorldMat");
|
||
Sprite3D.MVPMATRIX = Shader3D.propertyNameToID("u_MvpMatrix");
|
||
Sprite3D._uniqueIDCounter = 0;
|
||
|
||
class DrawMeshCMD extends Command {
|
||
constructor() {
|
||
super();
|
||
this._projectionViewWorldMatrix = new Matrix4x4();
|
||
this._renderShaderValue = new ShaderData();
|
||
this._renderShaderValue = new ShaderData(null);
|
||
}
|
||
static create(mesh, matrix, material, subMeshIndex, subShaderIndex, commandBuffer) {
|
||
var cmd;
|
||
cmd = DrawMeshCMD._pool.length > 0 ? DrawMeshCMD._pool.pop() : new DrawMeshCMD();
|
||
cmd._mesh = mesh;
|
||
cmd._matrix = matrix;
|
||
cmd._material = material;
|
||
cmd._subMeshIndex = subMeshIndex;
|
||
cmd._subShaderIndex = subShaderIndex;
|
||
cmd._commandBuffer = commandBuffer;
|
||
return cmd;
|
||
}
|
||
run() {
|
||
var renderSubShader = this._material._shader.getSubShaderAt(this._subShaderIndex);
|
||
this.setContext(this._commandBuffer._context);
|
||
var context = this._context;
|
||
var forceInvertFace = context.invertY;
|
||
var scene = context.scene;
|
||
var cameraShaderValue = context.cameraShaderValue;
|
||
var projectionView = context.projectionViewMatrix;
|
||
Matrix4x4.multiply(projectionView, this._matrix, this._projectionViewWorldMatrix);
|
||
this._renderShaderValue.setMatrix4x4(Sprite3D.WORLDMATRIX, this._matrix);
|
||
this._renderShaderValue.setMatrix4x4(Sprite3D.MVPMATRIX, this._projectionViewWorldMatrix);
|
||
var currentPipelineMode = context.pipelineMode;
|
||
var passes = renderSubShader._passes;
|
||
for (var j = 0, m = passes.length; j < m; j++) {
|
||
var pass = passes[j];
|
||
if (pass._pipelineMode !== currentPipelineMode)
|
||
continue;
|
||
var comDef = DrawMeshCMD._compileDefine;
|
||
scene._shaderValues._defineDatas.cloneTo(comDef);
|
||
comDef.addDefineDatas(this._renderShaderValue._defineDatas);
|
||
comDef.addDefineDatas(this._material._shaderValues._defineDatas);
|
||
var shaderIns = context.shader = pass.withCompile(comDef);
|
||
shaderIns.bind();
|
||
shaderIns.uploadUniforms(shaderIns._sceneUniformParamsMap, scene._shaderValues, true);
|
||
shaderIns.uploadUniforms(shaderIns._spriteUniformParamsMap, this._renderShaderValue, true);
|
||
shaderIns.uploadUniforms(shaderIns._cameraUniformParamsMap, cameraShaderValue, true);
|
||
var matValues = this._material._shaderValues;
|
||
shaderIns.uploadUniforms(shaderIns._materialUniformParamsMap, matValues, true);
|
||
shaderIns.uploadRenderStateBlendDepth(matValues);
|
||
shaderIns.uploadRenderStateFrontFace(matValues, forceInvertFace, this._matrix.getInvertFront());
|
||
}
|
||
var subGeometryElement = this._mesh._subMeshes;
|
||
var subMeshRender;
|
||
if (this._subMeshIndex == -1) {
|
||
for (var i = 0, n = subGeometryElement.length; i < n; i++) {
|
||
subMeshRender = subGeometryElement[i];
|
||
if (subMeshRender._prepareRender(context)) {
|
||
subMeshRender._render(context);
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
var subGeometryElement = this._mesh._subMeshes;
|
||
subMeshRender = subGeometryElement[this._subMeshIndex];
|
||
if (subMeshRender._prepareRender(context)) {
|
||
subMeshRender._render(context);
|
||
}
|
||
}
|
||
}
|
||
recover() {
|
||
DrawMeshCMD._pool.push(this);
|
||
this._renderShaderValue.clearDefine();
|
||
this._renderShaderValue._initData();
|
||
}
|
||
}
|
||
DrawMeshCMD._pool = [];
|
||
DrawMeshCMD._compileDefine = new DefineDatas();
|
||
|
||
class ClearRenderTextureCMD extends Command {
|
||
constructor() {
|
||
super(...arguments);
|
||
this._clearColor = false;
|
||
this._clearDepth = false;
|
||
this._backgroundColor = new Vector4();
|
||
this._depth = 1;
|
||
}
|
||
static create(clearColor, clearDepth, backgroundColor, depth = 1, commandBuffer) {
|
||
var cmd;
|
||
cmd = ClearRenderTextureCMD._pool.length > 0 ? ClearRenderTextureCMD._pool.pop() : new ClearRenderTextureCMD();
|
||
cmd._clearColor = clearColor;
|
||
cmd._clearDepth = clearDepth;
|
||
backgroundColor.cloneTo(cmd._backgroundColor);
|
||
cmd._depth = depth;
|
||
cmd._commandBuffer = commandBuffer;
|
||
return cmd;
|
||
}
|
||
run() {
|
||
var gl = Laya.LayaGL.instance;
|
||
var flag;
|
||
var backgroundColor = this._backgroundColor;
|
||
if (this._clearColor) {
|
||
gl.clearColor(backgroundColor.x, backgroundColor.y, backgroundColor.z, backgroundColor.w);
|
||
flag |= gl.COLOR_BUFFER_BIT;
|
||
}
|
||
if (this._clearDepth) {
|
||
gl.clearDepth(this._depth);
|
||
flag |= gl.DEPTH_BUFFER_BIT;
|
||
}
|
||
if (this._clearColor || this._clearDepth) {
|
||
gl.clear(flag);
|
||
}
|
||
}
|
||
recover() {
|
||
}
|
||
}
|
||
ClearRenderTextureCMD._pool = [];
|
||
|
||
class DrawRenderCMD extends Command {
|
||
static create(render, material, subShaderIndex, commandBuffer) {
|
||
var cmd;
|
||
cmd = DrawRenderCMD._pool.length > 0 ? DrawRenderCMD._pool.pop() : new DrawRenderCMD();
|
||
cmd._render = render;
|
||
cmd._material = material;
|
||
cmd._subShaderIndex = subShaderIndex;
|
||
cmd._commandBuffer = commandBuffer;
|
||
return cmd;
|
||
}
|
||
_elementRender(renderElement, context) {
|
||
var forceInvertFace = context.invertY;
|
||
var lastStateMaterial, lastStateShaderInstance, lastStateRender;
|
||
var updateMark = ILaya3D.Camera._updateMark;
|
||
var scene = context.scene;
|
||
this._render._scene = context.scene;
|
||
var cameraShaderValue = context.cameraShaderValue;
|
||
var transform = renderElement._transform;
|
||
var geometry = renderElement._geometry;
|
||
context.renderElement = renderElement;
|
||
var updateRender = updateMark !== renderElement.render._updateMark || renderElement.renderType !== renderElement.render._updateRenderType;
|
||
if (updateRender) {
|
||
renderElement.render._renderUpdate(context, transform);
|
||
renderElement.render._renderUpdateWithCamera(context, transform);
|
||
renderElement.render._updateMark = updateMark;
|
||
renderElement.render._updateRenderType = renderElement.renderType;
|
||
}
|
||
else {
|
||
if (renderElement.renderType == ILaya3D.RenderElement.RENDERTYPE_INSTANCEBATCH) {
|
||
renderElement.render._renderUpdate(context, transform);
|
||
renderElement.render._renderUpdateWithCamera(context, transform);
|
||
}
|
||
}
|
||
var currentPipelineMode = context.pipelineMode;
|
||
if (geometry._prepareRender(context)) {
|
||
var passes = renderElement.renderSubShader._passes;
|
||
for (var j = 0, m = passes.length; j < m; j++) {
|
||
var pass = passes[j];
|
||
if (pass._pipelineMode !== currentPipelineMode)
|
||
continue;
|
||
var comDef = DrawRenderCMD._compileDefine;
|
||
scene._shaderValues._defineDatas.cloneTo(comDef);
|
||
comDef.addDefineDatas(renderElement.render._shaderValues._defineDatas);
|
||
comDef.addDefineDatas(this._material._shaderValues._defineDatas);
|
||
var shaderIns = context.shader = pass.withCompile(comDef);
|
||
var switchShader = shaderIns.bind();
|
||
var switchUpdateMark = (updateMark !== shaderIns._uploadMark);
|
||
var uploadScene = (shaderIns._uploadScene !== scene) || switchUpdateMark;
|
||
if (uploadScene || switchShader) {
|
||
shaderIns.uploadUniforms(shaderIns._sceneUniformParamsMap, scene._shaderValues, uploadScene);
|
||
shaderIns._uploadScene = scene;
|
||
}
|
||
var uploadSprite3D = (shaderIns._uploadRender !== renderElement.render || shaderIns._uploadRenderType !== renderElement.renderType) || switchUpdateMark;
|
||
if (uploadSprite3D || switchShader) {
|
||
shaderIns.uploadUniforms(shaderIns._spriteUniformParamsMap, renderElement.render._shaderValues, uploadSprite3D);
|
||
shaderIns._uploadRender = renderElement.render;
|
||
shaderIns._uploadRenderType = renderElement.renderType;
|
||
}
|
||
var uploadCamera = shaderIns._uploadCameraShaderValue !== cameraShaderValue || switchUpdateMark;
|
||
if (uploadCamera || switchShader) {
|
||
shaderIns.uploadUniforms(shaderIns._cameraUniformParamsMap, cameraShaderValue, uploadCamera);
|
||
shaderIns._uploadCameraShaderValue = cameraShaderValue;
|
||
}
|
||
var uploadMaterial = (shaderIns._uploadMaterial !== this._material) || switchUpdateMark;
|
||
if (uploadMaterial || switchShader) {
|
||
shaderIns.uploadUniforms(shaderIns._materialUniformParamsMap, this._material._shaderValues, uploadMaterial);
|
||
shaderIns._uploadMaterial = this._material;
|
||
}
|
||
var matValues = this._material._shaderValues;
|
||
if (lastStateMaterial !== this._material || lastStateShaderInstance !== shaderIns) {
|
||
shaderIns.uploadRenderStateBlendDepth(matValues);
|
||
shaderIns.uploadRenderStateFrontFace(matValues, forceInvertFace, renderElement.getInvertFront());
|
||
lastStateMaterial = this._material;
|
||
lastStateShaderInstance = shaderIns;
|
||
lastStateRender = renderElement.render;
|
||
}
|
||
else {
|
||
if (lastStateRender !== renderElement.render) {
|
||
shaderIns.uploadRenderStateFrontFace(matValues, forceInvertFace, renderElement.getInvertFront());
|
||
lastStateRender = renderElement.render;
|
||
}
|
||
}
|
||
geometry._render(context);
|
||
shaderIns._uploadMark = updateMark;
|
||
}
|
||
}
|
||
if (renderElement.renderType !== ILaya3D.RenderElement.RENDERTYPE_NORMAL)
|
||
renderElement.render._revertBatchRenderUpdate(context);
|
||
}
|
||
run() {
|
||
if (!this._material)
|
||
throw "This render command material cannot be empty";
|
||
this.setContext(this._commandBuffer._context);
|
||
var context = this._context;
|
||
var scene = context.scene;
|
||
var renderElements = this._render._renderElements;
|
||
for (var i = 0, n = renderElements.length; i < n; i++) {
|
||
var renderelement = renderElements[i];
|
||
this._renderElementUpdate(renderelement);
|
||
this._elementRender(renderelement, context);
|
||
}
|
||
}
|
||
_renderElementUpdate(renderelement) {
|
||
if (this._material) {
|
||
renderelement.renderSubShader = this._material._shader.getSubShaderAt(this._subShaderIndex);
|
||
}
|
||
}
|
||
recover() {
|
||
DrawRenderCMD._pool.push(this);
|
||
}
|
||
}
|
||
DrawRenderCMD._pool = [];
|
||
DrawRenderCMD._compileDefine = new DefineDatas();
|
||
|
||
class SetGlobalShaderDataCMD extends Command {
|
||
constructor() {
|
||
super(...arguments);
|
||
this._nameID = 0;
|
||
this._value = null;
|
||
this._dataType = -1;
|
||
}
|
||
static create(nameID, value, shaderDataType, commandBuffer) {
|
||
var cmd;
|
||
cmd = SetGlobalShaderDataCMD._pool.length > 0 ? SetGlobalShaderDataCMD._pool.pop() : new SetGlobalShaderDataCMD();
|
||
cmd._nameID = nameID;
|
||
cmd._value = value;
|
||
cmd._dataType = shaderDataType;
|
||
cmd._commandBuffer = commandBuffer;
|
||
return cmd;
|
||
}
|
||
run() {
|
||
var shaderData = this._commandBuffer._camera.scene._shaderValues;
|
||
switch (this._dataType) {
|
||
case exports.ShaderDataType.Int:
|
||
shaderData.setInt(this._nameID, this._value);
|
||
break;
|
||
case exports.ShaderDataType.Number:
|
||
shaderData.setNumber(this._nameID, this._value);
|
||
break;
|
||
case exports.ShaderDataType.Bool:
|
||
shaderData.setBool(this._nameID, this._value);
|
||
break;
|
||
case exports.ShaderDataType.Matrix4x4:
|
||
shaderData.setMatrix4x4(this._nameID, this._value);
|
||
break;
|
||
case exports.ShaderDataType.Quaternion:
|
||
shaderData.setQuaternion(this._nameID, this._value);
|
||
break;
|
||
case exports.ShaderDataType.Texture:
|
||
shaderData.setTexture(this._nameID, this._value);
|
||
break;
|
||
case exports.ShaderDataType.Vector4:
|
||
shaderData.setVector(this._nameID, this._value);
|
||
break;
|
||
case exports.ShaderDataType.Vector2:
|
||
shaderData.setVector2(this._nameID, this._value);
|
||
break;
|
||
case exports.ShaderDataType.Vector3:
|
||
shaderData.setVector3(this._nameID, this._value);
|
||
break;
|
||
case exports.ShaderDataType.Buffer:
|
||
shaderData.setBuffer(this._nameID, this._value);
|
||
break;
|
||
default:
|
||
throw "no type shaderValue on this CommendBuffer";
|
||
}
|
||
}
|
||
recover() {
|
||
SetGlobalShaderDataCMD._pool.push(this);
|
||
this._nameID = 0;
|
||
this._value = null;
|
||
this._dataType = -1;
|
||
}
|
||
}
|
||
SetGlobalShaderDataCMD._pool = [];
|
||
|
||
class MeshSprite3DShaderDeclaration {
|
||
}
|
||
|
||
class VertexMesh {
|
||
static __init__() {
|
||
VertexMesh.instanceWorldMatrixDeclaration = new VertexDeclaration(64, [new VertexElement(0, VertexElementFormat.Vector4, VertexMesh.MESH_WORLDMATRIX_ROW0),
|
||
new VertexElement(16, VertexElementFormat.Vector4, VertexMesh.MESH_WORLDMATRIX_ROW1),
|
||
new VertexElement(32, VertexElementFormat.Vector4, VertexMesh.MESH_WORLDMATRIX_ROW2),
|
||
new VertexElement(48, VertexElementFormat.Vector4, VertexMesh.MESH_WORLDMATRIX_ROW3)]);
|
||
VertexMesh.instanceSimpleAnimatorDeclaration = new VertexDeclaration(16, [new VertexElement(0, VertexElementFormat.Vector4, VertexMesh.MESH_SIMPLEANIMATOR)]);
|
||
}
|
||
static getVertexDeclaration(vertexFlag, compatible = true) {
|
||
var verDec = VertexMesh._vertexDeclarationMap[vertexFlag + (compatible ? "_0" : "_1")];
|
||
if (!verDec) {
|
||
var subFlags = vertexFlag.split(",");
|
||
var offset = 0;
|
||
var elements = [];
|
||
for (var i = 0, n = subFlags.length; i < n; i++) {
|
||
var element;
|
||
switch (subFlags[i]) {
|
||
case "POSITION":
|
||
element = new VertexElement(offset, VertexElementFormat.Vector3, VertexMesh.MESH_POSITION0);
|
||
offset += 12;
|
||
break;
|
||
case "NORMAL":
|
||
element = new VertexElement(offset, VertexElementFormat.Vector3, VertexMesh.MESH_NORMAL0);
|
||
offset += 12;
|
||
break;
|
||
case "COLOR":
|
||
element = new VertexElement(offset, VertexElementFormat.Vector4, VertexMesh.MESH_COLOR0);
|
||
offset += 16;
|
||
break;
|
||
case "UV":
|
||
element = new VertexElement(offset, VertexElementFormat.Vector2, VertexMesh.MESH_TEXTURECOORDINATE0);
|
||
offset += 8;
|
||
break;
|
||
case "UV1":
|
||
element = new VertexElement(offset, VertexElementFormat.Vector2, VertexMesh.MESH_TEXTURECOORDINATE1);
|
||
offset += 8;
|
||
break;
|
||
case "BLENDWEIGHT":
|
||
element = new VertexElement(offset, VertexElementFormat.Vector4, VertexMesh.MESH_BLENDWEIGHT0);
|
||
offset += 16;
|
||
break;
|
||
case "BLENDINDICES":
|
||
if (compatible) {
|
||
element = new VertexElement(offset, VertexElementFormat.Vector4, VertexMesh.MESH_BLENDINDICES0);
|
||
offset += 16;
|
||
}
|
||
else {
|
||
element = new VertexElement(offset, VertexElementFormat.Byte4, VertexMesh.MESH_BLENDINDICES0);
|
||
offset += 4;
|
||
}
|
||
break;
|
||
case "TANGENT":
|
||
element = new VertexElement(offset, VertexElementFormat.Vector4, VertexMesh.MESH_TANGENT0);
|
||
offset += 16;
|
||
break;
|
||
default:
|
||
throw "VertexMesh: unknown vertex flag.";
|
||
}
|
||
elements.push(element);
|
||
}
|
||
verDec = new VertexDeclaration(offset, elements);
|
||
VertexMesh._vertexDeclarationMap[vertexFlag + (compatible ? "_0" : "_1")] = verDec;
|
||
}
|
||
return verDec;
|
||
}
|
||
}
|
||
VertexMesh.MESH_POSITION0 = 0;
|
||
VertexMesh.MESH_COLOR0 = 1;
|
||
VertexMesh.MESH_TEXTURECOORDINATE0 = 2;
|
||
VertexMesh.MESH_NORMAL0 = 3;
|
||
VertexMesh.MESH_TANGENT0 = 4;
|
||
VertexMesh.MESH_BLENDINDICES0 = 5;
|
||
VertexMesh.MESH_BLENDWEIGHT0 = 6;
|
||
VertexMesh.MESH_TEXTURECOORDINATE1 = 7;
|
||
VertexMesh.MESH_WORLDMATRIX_ROW0 = 8;
|
||
VertexMesh.MESH_WORLDMATRIX_ROW1 = 9;
|
||
VertexMesh.MESH_WORLDMATRIX_ROW2 = 10;
|
||
VertexMesh.MESH_WORLDMATRIX_ROW3 = 11;
|
||
VertexMesh.MESH_SIMPLEANIMATOR = 12;
|
||
VertexMesh.MESH_CUSTOME0 = 12;
|
||
VertexMesh.MESH_CUSTOME1 = 13;
|
||
VertexMesh.MESH_CUSTOME2 = 14;
|
||
VertexMesh.MESH_CUSTOME3 = 15;
|
||
VertexMesh._vertexDeclarationMap = {};
|
||
|
||
class DrawMeshInstancedCMD extends Command {
|
||
constructor() {
|
||
super();
|
||
this._renderShaderValue = new ShaderData(null);
|
||
let gl = Laya.LayaGL.instance;
|
||
this._instanceWorldMatrixData = new Float32Array(DrawMeshInstancedCMD.maxInstanceCount * 16);
|
||
this._instanceWorldMatrixBuffer = new VertexBuffer3D(this._instanceWorldMatrixData.length * 4, gl.DYNAMIC_DRAW);
|
||
this._instanceWorldMatrixBuffer.vertexDeclaration = VertexMesh.instanceWorldMatrixDeclaration;
|
||
}
|
||
static create(mesh, subMeshIndex, matrixs, material, subShaderIndex, instanceProperty, drawnums, commandBuffer) {
|
||
var cmd;
|
||
if ((matrixs && matrixs.length > 1024) || drawnums > DrawMeshInstancedCMD.maxInstanceCount) {
|
||
throw "the number of renderings exceeds the maximum number of merges";
|
||
}
|
||
cmd = DrawMeshInstancedCMD._pool.length > 0 ? DrawMeshInstancedCMD._pool.pop() : new DrawMeshInstancedCMD();
|
||
cmd._mesh = mesh;
|
||
cmd._matrixs = matrixs;
|
||
cmd._material = material;
|
||
cmd._subMeshIndex = subMeshIndex;
|
||
cmd._subShaderIndex = subShaderIndex;
|
||
cmd._commandBuffer = commandBuffer;
|
||
cmd._instanceProperty = instanceProperty;
|
||
cmd._drawnums = drawnums;
|
||
matrixs || cmd._updateWorldMatrixBuffer();
|
||
cmd._setInstanceBuffer();
|
||
return cmd;
|
||
}
|
||
_setInstanceBuffer() {
|
||
let instanceBufferState = this._instanceBufferState = new BufferState();
|
||
instanceBufferState.bind();
|
||
instanceBufferState.applyVertexBuffer(this._mesh._vertexBuffer);
|
||
instanceBufferState.applyInstanceVertexBuffer(this._instanceWorldMatrixBuffer);
|
||
let propertyMap = this._instanceProperty._propertyMap;
|
||
for (let i in propertyMap) {
|
||
instanceBufferState.applyInstanceVertexBuffer(propertyMap[i]._vertexBuffer);
|
||
}
|
||
instanceBufferState.applyIndexBuffer(this._mesh._indexBuffer);
|
||
instanceBufferState.unBind();
|
||
}
|
||
_updateWorldMatrixBuffer() {
|
||
let worldMatrixData = this._instanceWorldMatrixData;
|
||
let count = this._drawnums;
|
||
for (let i = 0; i < count; i++) {
|
||
worldMatrixData.set(this._matrixs[i].elements, i * 16);
|
||
}
|
||
let worldBuffer = this._instanceWorldMatrixBuffer;
|
||
worldBuffer.orphanStorage();
|
||
worldBuffer.setData(worldMatrixData.buffer, 0, 0, count * 64);
|
||
}
|
||
_render(subMesh) {
|
||
let gl = Laya.LayaGL.instance;
|
||
var count = this._drawnums;
|
||
var indexCount = subMesh._indexCount;
|
||
this._instanceBufferState.bind();
|
||
Laya.LayaGL.layaGPUInstance.drawElementsInstanced(gl.TRIANGLES, indexCount, gl.UNSIGNED_SHORT, subMesh._indexStart * 2, count);
|
||
Laya.Stat.renderBatches++;
|
||
Laya.Stat.trianglesFaces += indexCount * count / 3;
|
||
}
|
||
run() {
|
||
let renderSubShader = this._material._shader.getSubShaderAt(this._subShaderIndex);
|
||
this.setContext(this._commandBuffer._context);
|
||
let context = this._context;
|
||
let forceInvertFace = context.invertY;
|
||
let scene = context.scene;
|
||
let cameraShaderValue = context.cameraShaderValue;
|
||
let currentPipelineMode = context.pipelineMode;
|
||
this._renderShaderValue.addDefine(MeshSprite3DShaderDeclaration.SHADERDEFINE_GPU_INSTANCE);
|
||
let passes = renderSubShader._passes;
|
||
for (let j = 0, m = passes.length; j < m; j++) {
|
||
let pass = passes[j];
|
||
if (pass._pipelineMode !== currentPipelineMode)
|
||
continue;
|
||
let comDef = DrawMeshInstancedCMD._compileDefine;
|
||
scene._shaderValues._defineDatas.cloneTo(comDef);
|
||
comDef.addDefineDatas(this._renderShaderValue._defineDatas);
|
||
comDef.addDefineDatas(this._material._shaderValues._defineDatas);
|
||
let shaderIns = context.shader = pass.withCompile(comDef);
|
||
shaderIns.bind();
|
||
shaderIns.uploadUniforms(shaderIns._sceneUniformParamsMap, scene._shaderValues, true);
|
||
shaderIns.uploadUniforms(shaderIns._spriteUniformParamsMap, this._renderShaderValue, true);
|
||
shaderIns.uploadUniforms(shaderIns._cameraUniformParamsMap, cameraShaderValue, true);
|
||
let matValues = this._material._shaderValues;
|
||
shaderIns.uploadUniforms(shaderIns._materialUniformParamsMap, matValues, true);
|
||
shaderIns.uploadRenderStateBlendDepth(matValues);
|
||
shaderIns.uploadRenderStateFrontFace(matValues, forceInvertFace, false);
|
||
}
|
||
let propertyMap = this._instanceProperty._propertyMap;
|
||
for (let i in propertyMap) {
|
||
propertyMap[i].updateVertexBufferData(this._drawnums);
|
||
}
|
||
let subGeometryElement = this._mesh._subMeshes;
|
||
let subMeshRender;
|
||
if (this._subMeshIndex == -1) {
|
||
for (let i = 0, n = subGeometryElement.length; i < n; i++) {
|
||
subMeshRender = subGeometryElement[i];
|
||
if (subMeshRender._prepareRender(context)) {
|
||
this._render(subMeshRender);
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
let subGeometryElement = this._mesh._subMeshes;
|
||
subMeshRender = subGeometryElement[this._subMeshIndex];
|
||
if (subMeshRender._prepareRender(context)) {
|
||
this._render(subMeshRender);
|
||
}
|
||
}
|
||
}
|
||
setWorldMatrix(worldMatrixArray) {
|
||
if (worldMatrixArray.length < this._drawnums)
|
||
throw "worldMatrixArray length is less then drawnums";
|
||
this._matrixs = worldMatrixArray;
|
||
this._matrixs && this._updateWorldMatrixBuffer();
|
||
}
|
||
setDrawNums(drawNums) {
|
||
if (this._matrixs && this._matrixs.length < drawNums)
|
||
throw "worldMatrixArray length is less then drawnums";
|
||
this._drawnums = drawNums;
|
||
this._matrixs && this._updateWorldMatrixBuffer();
|
||
}
|
||
recover() {
|
||
DrawMeshInstancedCMD._pool.push(this);
|
||
this._renderShaderValue.clearDefine();
|
||
this._renderShaderValue._initData();
|
||
this._instanceBufferState.destroy();
|
||
this._instanceBufferState = null;
|
||
}
|
||
}
|
||
DrawMeshInstancedCMD._pool = [];
|
||
DrawMeshInstancedCMD._compileDefine = new DefineDatas();
|
||
DrawMeshInstancedCMD.maxInstanceCount = 1024;
|
||
|
||
class CommandBuffer {
|
||
constructor() {
|
||
this._camera = null;
|
||
this._commands = [];
|
||
}
|
||
_apply() {
|
||
for (var i = 0, n = this._commands.length; i < n; i++)
|
||
this._commands[i].run();
|
||
}
|
||
setShaderDataTexture(shaderData, nameID, source) {
|
||
this._commands.push(SetShaderDataCMD.create(shaderData, nameID, source, exports.ShaderDataType.Texture, this));
|
||
}
|
||
setGlobalTexture(nameID, source) {
|
||
this._commands.push(SetGlobalShaderDataCMD.create(nameID, source, exports.ShaderDataType.Texture, this));
|
||
}
|
||
setShaderDataVector(shaderData, nameID, value) {
|
||
this._commands.push(SetShaderDataCMD.create(shaderData, nameID, value, exports.ShaderDataType.Vector4, this));
|
||
}
|
||
setGlobalVector(nameID, source) {
|
||
this._commands.push(SetGlobalShaderDataCMD.create(nameID, source, exports.ShaderDataType.Vector4, this));
|
||
}
|
||
setShaderDataVector3(shaderData, nameID, value) {
|
||
this._commands.push(SetShaderDataCMD.create(shaderData, nameID, value, exports.ShaderDataType.Vector3, this));
|
||
}
|
||
setGlobalVector3(nameID, source) {
|
||
this._commands.push(SetGlobalShaderDataCMD.create(nameID, source, exports.ShaderDataType.Vector3, this));
|
||
}
|
||
setShaderDataVector2(shaderData, nameID, value) {
|
||
this._commands.push(SetShaderDataCMD.create(shaderData, nameID, value, exports.ShaderDataType.Vector2, this));
|
||
}
|
||
setGlobalVector2(nameID, source) {
|
||
this._commands.push(SetGlobalShaderDataCMD.create(nameID, source, exports.ShaderDataType.Vector2, this));
|
||
}
|
||
setShaderDataNumber(shaderData, nameID, value) {
|
||
this._commands.push(SetShaderDataCMD.create(shaderData, nameID, value, exports.ShaderDataType.Number, this));
|
||
}
|
||
setGlobalNumber(nameID, source) {
|
||
this._commands.push(SetGlobalShaderDataCMD.create(nameID, source, exports.ShaderDataType.Number, this));
|
||
}
|
||
setShaderDataInt(shaderData, nameID, value) {
|
||
this._commands.push(SetShaderDataCMD.create(shaderData, nameID, value, exports.ShaderDataType.Int, this));
|
||
}
|
||
setGlobalInt(nameID, source) {
|
||
this._commands.push(SetGlobalShaderDataCMD.create(nameID, source, exports.ShaderDataType.Int, this));
|
||
}
|
||
setShaderDataMatrix(shaderData, nameID, value) {
|
||
this._commands.push(SetShaderDataCMD.create(shaderData, nameID, value, exports.ShaderDataType.Matrix4x4, this));
|
||
}
|
||
setGlobalMatrix(nameID, source) {
|
||
this._commands.push(SetGlobalShaderDataCMD.create(nameID, source, exports.ShaderDataType.Matrix4x4, this));
|
||
}
|
||
blitScreenQuad(source, dest, offsetScale = null, shader = null, shaderData = null, subShader = 0, definedCanvas = false) {
|
||
this._commands.push(BlitScreenQuadCMD.create(source, dest, offsetScale, shader, shaderData, subShader, BlitScreenQuadCMD._SCREENTYPE_QUAD, this, definedCanvas));
|
||
}
|
||
blitScreenQuadByMaterial(source, dest, offsetScale = null, material = null, subShader = 0) {
|
||
var shader;
|
||
var shaderData;
|
||
if (material) {
|
||
shader = material._shader;
|
||
shaderData = material.shaderData;
|
||
}
|
||
this._commands.push(BlitScreenQuadCMD.create(source, dest, offsetScale, shader, shaderData, subShader, BlitScreenQuadCMD._SCREENTYPE_QUAD, this));
|
||
}
|
||
blitScreenTriangle(source, dest, offsetScale = null, shader = null, shaderData = null, subShader = 0, defineCanvas = false) {
|
||
this._commands.push(BlitScreenQuadCMD.create(source, dest, offsetScale, shader, shaderData, subShader, BlitScreenQuadCMD._SCREENTYPE_TRIANGLE, this, defineCanvas));
|
||
}
|
||
setRenderTarget(renderTexture) {
|
||
this._commands.push(SetRenderTargetCMD.create(renderTexture));
|
||
}
|
||
clearRenderTarget(clearColor, clearDepth, backgroundColor, depth = 1) {
|
||
this._commands.push(ClearRenderTextureCMD.create(clearColor, clearDepth, backgroundColor, depth, this));
|
||
}
|
||
drawMesh(mesh, matrix, material, submeshIndex, subShaderIndex) {
|
||
this._commands.push(DrawMeshCMD.create(mesh, matrix, material, submeshIndex, subShaderIndex, this));
|
||
}
|
||
drawRender(render, material, subShaderIndex) {
|
||
this._commands.push(DrawRenderCMD.create(render, material, subShaderIndex, this));
|
||
}
|
||
drawMeshInstance(mesh, subMeshIndex, matrixs, material, subShaderIndex, instanceProperty, drawnums) {
|
||
if (!Laya.LayaGL.layaGPUInstance.supportInstance())
|
||
return null;
|
||
var drawMeshInstancedCMD = DrawMeshInstancedCMD.create(mesh, subMeshIndex, matrixs, material, subShaderIndex, instanceProperty, drawnums, this);
|
||
this._commands.push(drawMeshInstancedCMD);
|
||
return drawMeshInstancedCMD;
|
||
}
|
||
clear() {
|
||
for (var i = 0, n = this._commands.length; i < n; i++)
|
||
this._commands[i].recover();
|
||
this._commands.length = 0;
|
||
}
|
||
}
|
||
|
||
class PostProcessRenderContext {
|
||
constructor() {
|
||
this.source = null;
|
||
this.destination = null;
|
||
this.camera = null;
|
||
this.compositeShaderData = null;
|
||
this.command = null;
|
||
this.deferredReleaseTextures = [];
|
||
}
|
||
}
|
||
|
||
class PostProcess {
|
||
constructor() {
|
||
this._compositeShader = Shader3D.find("PostProcessComposite");
|
||
this._compositeShaderData = new ShaderData();
|
||
this._effects = [];
|
||
this._enable = true;
|
||
this._context = null;
|
||
this._context = new PostProcessRenderContext();
|
||
this._context.compositeShaderData = this._compositeShaderData;
|
||
this._context.command = new CommandBuffer();
|
||
}
|
||
static __init__() {
|
||
PostProcess.SHADERDEFINE_BLOOM_LOW = Shader3D.getDefineByName("BLOOM_LOW");
|
||
PostProcess.SHADERDEFINE_BLOOM = Shader3D.getDefineByName("BLOOM");
|
||
PostProcess.SHADERDEFINE_FINALPASS = Shader3D.getDefineByName("FINALPASS");
|
||
}
|
||
get enable() {
|
||
return this._enable;
|
||
}
|
||
set enable(value) {
|
||
this._enable = value;
|
||
}
|
||
_init(camera) {
|
||
this._context.camera = camera;
|
||
this._context.command._camera = camera;
|
||
}
|
||
_render() {
|
||
var noteValue = ShaderData._SET_RUNTIME_VALUE_MODE_REFERENCE_;
|
||
Laya.ILaya.Render.supportWebGLPlusRendering && ShaderData.setRuntimeValueMode(false);
|
||
var camera = this._context.camera;
|
||
var viewport = camera.viewport;
|
||
var cameraTarget = camera._internalRenderTexture;
|
||
var screenTexture = cameraTarget;
|
||
this._context.command.clear();
|
||
this._context.source = screenTexture;
|
||
this._context.destination = cameraTarget;
|
||
this._context.compositeShaderData.clearDefine();
|
||
this._context.compositeShaderData.setTexture(PostProcess.SHADERVALUE_AUTOEXPOSURETEX, Laya.Texture2D.whiteTexture);
|
||
for (var i = 0, n = this._effects.length; i < n; i++)
|
||
this._effects[i].render(this._context);
|
||
this._compositeShaderData.addDefine(PostProcess.SHADERDEFINE_FINALPASS);
|
||
var offScreenTex = camera._offScreenRenderTexture;
|
||
var dest = offScreenTex ? offScreenTex : null;
|
||
this._context.destination = dest;
|
||
var canvasWidth = camera._getCanvasWidth(), canvasHeight = camera._getCanvasHeight();
|
||
camera._screenOffsetScale.setValue(viewport.x / canvasWidth, viewport.y / canvasHeight, viewport.width / canvasWidth, viewport.height / canvasHeight);
|
||
this._context.command.blitScreenTriangle(this._context.source, dest, camera._screenOffsetScale, this._compositeShader, this._compositeShaderData, 0, true);
|
||
RenderTexture.recoverToPool(screenTexture);
|
||
var tempRenderTextures = this._context.deferredReleaseTextures;
|
||
for (i = 0, n = tempRenderTextures.length; i < n; i++)
|
||
RenderTexture.recoverToPool(tempRenderTextures[i]);
|
||
tempRenderTextures.length = 0;
|
||
Laya.ILaya.Render.supportWebGLPlusRendering && ShaderData.setRuntimeValueMode(noteValue);
|
||
}
|
||
addEffect(effect) {
|
||
this._effects.push(effect);
|
||
}
|
||
removeEffect(effect) {
|
||
var index = this._effects.indexOf(effect);
|
||
if (index !== -1)
|
||
this._effects.splice(index, 1);
|
||
}
|
||
_applyPostProcessCommandBuffers() {
|
||
this._context.command._apply();
|
||
}
|
||
}
|
||
PostProcess.SHADERVALUE_MAINTEX = Shader3D.propertyNameToID("u_MainTex");
|
||
PostProcess.SHADERVALUE_BLOOMTEX = Shader3D.propertyNameToID("u_BloomTex");
|
||
PostProcess.SHADERVALUE_AUTOEXPOSURETEX = Shader3D.propertyNameToID("u_AutoExposureTex");
|
||
PostProcess.SHADERVALUE_BLOOM_DIRTTEX = Shader3D.propertyNameToID("u_Bloom_DirtTex");
|
||
PostProcess.SHADERVALUE_BLOOMTEX_TEXELSIZE = Shader3D.propertyNameToID("u_BloomTex_TexelSize");
|
||
PostProcess.SHADERVALUE_BLOOM_DIRTTILEOFFSET = Shader3D.propertyNameToID("u_Bloom_DirtTileOffset");
|
||
PostProcess.SHADERVALUE_BLOOM_SETTINGS = Shader3D.propertyNameToID("u_Bloom_Settings");
|
||
PostProcess.SHADERVALUE_BLOOM_COLOR = Shader3D.propertyNameToID("u_Bloom_Color");
|
||
|
||
class AnimationTransform3D extends Laya.EventDispatcher {
|
||
constructor(owner) {
|
||
super();
|
||
this._owner = owner;
|
||
this._children = [];
|
||
this._localMatrix = new Float32Array(16);
|
||
this._localPosition = new Vector3();
|
||
this._localRotation = new Quaternion();
|
||
this._localScale = new Vector3();
|
||
this._worldMatrix = new Float32Array(16);
|
||
this._localQuaternionUpdate = false;
|
||
this._locaEulerlUpdate = false;
|
||
this._localUpdate = false;
|
||
this._worldUpdate = true;
|
||
}
|
||
_getlocalMatrix() {
|
||
if (this._localUpdate) {
|
||
Utils3D._createAffineTransformationArray(this._localPosition, this._localRotation, this._localScale, this._localMatrix);
|
||
this._localUpdate = false;
|
||
}
|
||
return this._localMatrix;
|
||
}
|
||
_onWorldTransform() {
|
||
if (!this._worldUpdate) {
|
||
this._worldUpdate = true;
|
||
this.event(Laya.Event.TRANSFORM_CHANGED);
|
||
for (var i = 0, n = this._children.length; i < n; i++)
|
||
this._children[i]._onWorldTransform();
|
||
}
|
||
}
|
||
get localPosition() {
|
||
return this._localPosition;
|
||
}
|
||
set localPosition(value) {
|
||
this._localPosition = value;
|
||
this._localUpdate = true;
|
||
this._onWorldTransform();
|
||
}
|
||
get localRotation() {
|
||
if (this._localQuaternionUpdate) {
|
||
var euler = this._localRotationEuler;
|
||
Quaternion.createFromYawPitchRoll(euler.y / AnimationTransform3D._angleToRandin, euler.x / AnimationTransform3D._angleToRandin, euler.z / AnimationTransform3D._angleToRandin, this._localRotation);
|
||
this._localQuaternionUpdate = false;
|
||
}
|
||
return this._localRotation;
|
||
}
|
||
set localRotation(value) {
|
||
this._localRotation = value;
|
||
this._locaEulerlUpdate = true;
|
||
this._localQuaternionUpdate = false;
|
||
this._localUpdate = true;
|
||
this._onWorldTransform();
|
||
}
|
||
get localScale() {
|
||
return this._localScale;
|
||
}
|
||
set localScale(value) {
|
||
this._localScale = value;
|
||
this._localUpdate = true;
|
||
this._onWorldTransform();
|
||
}
|
||
get localRotationEuler() {
|
||
if (this._locaEulerlUpdate) {
|
||
this._localRotation.getYawPitchRoll(AnimationTransform3D._tempVector3);
|
||
var euler = AnimationTransform3D._tempVector3;
|
||
var localRotationEuler = this._localRotationEuler;
|
||
localRotationEuler.x = euler.y * AnimationTransform3D._angleToRandin;
|
||
localRotationEuler.y = euler.x * AnimationTransform3D._angleToRandin;
|
||
localRotationEuler.z = euler.z * AnimationTransform3D._angleToRandin;
|
||
this._locaEulerlUpdate = false;
|
||
}
|
||
return this._localRotationEuler;
|
||
}
|
||
set localRotationEuler(value) {
|
||
this._localRotationEuler = value;
|
||
this._locaEulerlUpdate = false;
|
||
this._localQuaternionUpdate = true;
|
||
this._localUpdate = true;
|
||
this._onWorldTransform();
|
||
}
|
||
getWorldMatrix() {
|
||
if (this._worldUpdate) {
|
||
if (this._parent != null) {
|
||
Utils3D.matrix4x4MultiplyFFF(this._parent.getWorldMatrix(), this._getlocalMatrix(), this._worldMatrix);
|
||
}
|
||
else {
|
||
var e = this._worldMatrix;
|
||
e[1] = e[2] = e[3] = e[4] = e[6] = e[7] = e[8] = e[9] = e[11] = e[12] = e[13] = e[14] = 0;
|
||
e[0] = e[5] = e[10] = e[15] = 1;
|
||
}
|
||
this._worldUpdate = false;
|
||
}
|
||
return this._worldMatrix;
|
||
}
|
||
setParent(value) {
|
||
if (this._parent !== value) {
|
||
if (this._parent) {
|
||
var parentChilds = this._parent._children;
|
||
var index = parentChilds.indexOf(this);
|
||
parentChilds.splice(index, 1);
|
||
}
|
||
if (value) {
|
||
value._children.push(this);
|
||
(value) && (this._onWorldTransform());
|
||
}
|
||
this._parent = value;
|
||
}
|
||
}
|
||
}
|
||
AnimationTransform3D._tempVector3 = new Vector3();
|
||
AnimationTransform3D._angleToRandin = 180 / Math.PI;
|
||
|
||
class AnimationNode {
|
||
constructor() {
|
||
this._parent = null;
|
||
this.name = null;
|
||
this._worldMatrixIndex = 0;
|
||
this._children = [];
|
||
this.transform = new AnimationTransform3D(this);
|
||
}
|
||
addChild(child) {
|
||
child._parent = this;
|
||
child.transform.setParent(this.transform);
|
||
this._children.push(child);
|
||
}
|
||
removeChild(child) {
|
||
var index = this._children.indexOf(child);
|
||
(index !== -1) && (this._children.splice(index, 1));
|
||
}
|
||
getChildByName(name) {
|
||
for (var i = 0, n = this._children.length; i < n; i++) {
|
||
var child = this._children[i];
|
||
if (child.name === name)
|
||
return child;
|
||
}
|
||
return null;
|
||
}
|
||
getChildByIndex(index) {
|
||
return this._children[index];
|
||
}
|
||
getChildCount() {
|
||
return this._children.length;
|
||
}
|
||
cloneTo(destObject) {
|
||
var destNode = destObject;
|
||
destNode.name = this.name;
|
||
for (var i = 0, n = this._children.length; i < n; i++) {
|
||
var child = this._children[i];
|
||
var destChild = child.clone();
|
||
destNode.addChild(destChild);
|
||
var transform = child.transform;
|
||
var destTransform = destChild.transform;
|
||
var destLocalPosition = destTransform.localPosition;
|
||
var destLocalRotation = destTransform.localRotation;
|
||
var destLocalScale = destTransform.localScale;
|
||
transform.localPosition.cloneTo(destLocalPosition);
|
||
transform.localRotation.cloneTo(destLocalRotation);
|
||
transform.localScale.cloneTo(destLocalScale);
|
||
destTransform.localPosition = destLocalPosition;
|
||
destTransform.localRotation = destLocalRotation;
|
||
destTransform.localScale = destLocalScale;
|
||
}
|
||
}
|
||
clone() {
|
||
var dest = new AnimationNode();
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
_cloneNative(localPositions, localRotations, localScales, animationNodeWorldMatrixs, animationNodeParentIndices, parentIndex, avatar) {
|
||
var curID = avatar._nativeCurCloneCount;
|
||
animationNodeParentIndices[curID] = parentIndex;
|
||
var dest = new AnimationNode();
|
||
dest._worldMatrixIndex = curID;
|
||
this._cloneToNative(dest, localPositions, localRotations, localScales, animationNodeWorldMatrixs, animationNodeParentIndices, curID, avatar);
|
||
return dest;
|
||
}
|
||
_cloneToNative(destObject, localPositions, localRotations, localScales, animationNodeWorldMatrixs, animationNodeParentIndices, parentIndex, avatar) {
|
||
var destNode = destObject;
|
||
destNode.name = this.name;
|
||
for (var i = 0, n = this._children.length; i < n; i++) {
|
||
var child = this._children[i];
|
||
avatar._nativeCurCloneCount++;
|
||
var destChild = child._cloneNative(localPositions, localRotations, localScales, animationNodeWorldMatrixs, animationNodeParentIndices, parentIndex, avatar);
|
||
destNode.addChild(destChild);
|
||
var transform = child.transform;
|
||
var destTransform = destChild.transform;
|
||
var destLocalPosition = destTransform.localPosition;
|
||
var destLocalRotation = destTransform.localRotation;
|
||
var destLocalScale = destTransform.localScale;
|
||
transform.localPosition.cloneTo(destLocalPosition);
|
||
transform.localRotation.cloneTo(destLocalRotation);
|
||
transform.localScale.cloneTo(destLocalScale);
|
||
destTransform.localPosition = destLocalPosition;
|
||
destTransform.localRotation = destLocalRotation;
|
||
destTransform.localScale = destLocalScale;
|
||
}
|
||
}
|
||
}
|
||
|
||
class Avatar extends Laya.Resource {
|
||
constructor() {
|
||
super();
|
||
this._nativeNodeCount = 0;
|
||
this._nativeCurCloneCount = 0;
|
||
}
|
||
static _parse(data, propertyParams = null, constructParams = null) {
|
||
var avatar = new Avatar();
|
||
avatar._rootNode = new AnimationNode();
|
||
if (data.version) {
|
||
var rootNode = data.rootNode;
|
||
(rootNode) && (avatar._parseNode(rootNode, avatar._rootNode));
|
||
}
|
||
return avatar;
|
||
}
|
||
static load(url, complete) {
|
||
Laya.ILaya.loader.create(url, complete, null, Avatar.AVATAR);
|
||
}
|
||
_initCloneToAnimator(destNode, destAnimator) {
|
||
destAnimator._avatarNodeMap[destNode.name] = destNode;
|
||
for (var i = 0, n = destNode.getChildCount(); i < n; i++)
|
||
this._initCloneToAnimator(destNode.getChildByIndex(i), destAnimator);
|
||
}
|
||
_parseNode(nodaData, node) {
|
||
var name = nodaData.props.name;
|
||
node.name = name;
|
||
var props = nodaData.props;
|
||
var transform = node.transform;
|
||
var pos = transform.localPosition;
|
||
var rot = transform.localRotation;
|
||
var sca = transform.localScale;
|
||
pos.fromArray(props.translate);
|
||
rot.fromArray(props.rotation);
|
||
sca.fromArray(props.scale);
|
||
transform.localPosition = pos;
|
||
transform.localRotation = rot;
|
||
transform.localScale = sca;
|
||
var childrenData = nodaData.child;
|
||
for (var j = 0, n = childrenData.length; j < n; j++) {
|
||
var childData = childrenData[j];
|
||
var childBone = new AnimationNode();
|
||
node.addChild(childBone);
|
||
this._parseNode(childData, childBone);
|
||
}
|
||
}
|
||
_cloneDatasToAnimator(destAnimator) {
|
||
var destRoot;
|
||
destRoot = this._rootNode.clone();
|
||
var transform = this._rootNode.transform;
|
||
var destTransform = destRoot.transform;
|
||
var destPosition = destTransform.localPosition;
|
||
var destRotation = destTransform.localRotation;
|
||
var destScale = destTransform.localScale;
|
||
transform.localPosition.cloneTo(destPosition);
|
||
transform.localRotation.cloneTo(destRotation);
|
||
transform.localScale.cloneTo(destScale);
|
||
destTransform.localPosition = destPosition;
|
||
destTransform.localRotation = destRotation;
|
||
destTransform.localScale = destScale;
|
||
destAnimator._avatarNodeMap = {};
|
||
this._initCloneToAnimator(destRoot, destAnimator);
|
||
}
|
||
cloneTo(destObject) {
|
||
var destAvatar = destObject;
|
||
var destRoot = this._rootNode.clone();
|
||
destAvatar._rootNode = destRoot;
|
||
}
|
||
clone() {
|
||
var dest = new Avatar();
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
_cloneDatasToAnimatorNative(destAnimator) {
|
||
var animationNodeLocalPositions = new Float32Array(this._nativeNodeCount * 3);
|
||
var animationNodeLocalRotations = new Float32Array(this._nativeNodeCount * 4);
|
||
var animationNodeLocalScales = new Float32Array(this._nativeNodeCount * 3);
|
||
var animationNodeWorldMatrixs = new Float32Array(this._nativeNodeCount * 16);
|
||
var animationNodeParentIndices = new Int16Array(this._nativeNodeCount);
|
||
destAnimator._animationNodeLocalPositions = animationNodeLocalPositions;
|
||
destAnimator._animationNodeLocalRotations = animationNodeLocalRotations;
|
||
destAnimator._animationNodeLocalScales = animationNodeLocalScales;
|
||
destAnimator._animationNodeWorldMatrixs = animationNodeWorldMatrixs;
|
||
destAnimator._animationNodeParentIndices = animationNodeParentIndices;
|
||
this._nativeCurCloneCount = 0;
|
||
var destRoot = this._rootNode._cloneNative(animationNodeLocalPositions, animationNodeLocalRotations, animationNodeLocalScales, animationNodeWorldMatrixs, animationNodeParentIndices, -1, this);
|
||
var transform = this._rootNode.transform;
|
||
var destTransform = destRoot.transform;
|
||
var destPosition = destTransform.localPosition;
|
||
var destRotation = destTransform.localRotation;
|
||
var destScale = destTransform.localScale;
|
||
transform.localPosition.cloneTo(destPosition);
|
||
transform.localRotation.cloneTo(destRotation);
|
||
transform.localScale.cloneTo(destScale);
|
||
destTransform.localPosition = destPosition;
|
||
destTransform.localRotation = destRotation;
|
||
destTransform.localScale = destScale;
|
||
destAnimator._avatarNodeMap = {};
|
||
this._initCloneToAnimator(destRoot, destAnimator);
|
||
}
|
||
}
|
||
Avatar.AVATAR = "AVATAR";
|
||
|
||
class Material extends Laya.Resource {
|
||
constructor() {
|
||
super();
|
||
this._shaderValues = new ShaderData(this);
|
||
this.renderQueue = Material.RENDERQUEUE_OPAQUE;
|
||
this.alphaTest = false;
|
||
}
|
||
static load(url, complete) {
|
||
Laya.Laya.loader.create(url, complete, null, Material.MATERIAL);
|
||
}
|
||
static __initDefine__() {
|
||
Material.SHADERDEFINE_ALPHATEST = Shader3D.getDefineByName("ALPHATEST");
|
||
}
|
||
static _parse(data, propertyParams = null, constructParams = null) {
|
||
var jsonData = data;
|
||
var props = jsonData.props;
|
||
var material;
|
||
var classType = props.type;
|
||
var clas = Laya.ClassUtils.getRegClass(classType);
|
||
if (clas)
|
||
material = new clas();
|
||
else {
|
||
material = new Material();
|
||
material.setShaderName(classType);
|
||
}
|
||
switch (jsonData.version) {
|
||
case "LAYAMATERIAL:01":
|
||
case "LAYAMATERIAL:02":
|
||
var i, n;
|
||
for (var key in props) {
|
||
switch (key) {
|
||
case "type":
|
||
break;
|
||
case "vectors":
|
||
var vectors = props[key];
|
||
for (i = 0, n = vectors.length; i < n; i++) {
|
||
var vector = vectors[i];
|
||
var vectorValue = vector.value;
|
||
switch (vectorValue.length) {
|
||
case 2:
|
||
material[vector.name] = new Vector2(vectorValue[0], vectorValue[1]);
|
||
break;
|
||
case 3:
|
||
material[vector.name] = new Vector3(vectorValue[0], vectorValue[1], vectorValue[2]);
|
||
break;
|
||
case 4:
|
||
material[vector.name] = new Vector4(vectorValue[0], vectorValue[1], vectorValue[2], vectorValue[3]);
|
||
break;
|
||
default:
|
||
throw new Error("BaseMaterial:unkonwn color length.");
|
||
}
|
||
}
|
||
break;
|
||
case "textures":
|
||
var textures = props[key];
|
||
for (i = 0, n = textures.length; i < n; i++) {
|
||
var texture = textures[i];
|
||
var path = texture.path;
|
||
(path) && (material[texture.name] = Laya.Loader.getRes(path));
|
||
}
|
||
break;
|
||
case "defines":
|
||
var defineNames = props[key];
|
||
for (i = 0, n = defineNames.length; i < n; i++) {
|
||
var define = Shader3D.getDefineByName(defineNames[i]);
|
||
material._shaderValues.addDefine(define);
|
||
}
|
||
break;
|
||
case "renderStates":
|
||
var renderStatesData = props[key];
|
||
var renderStateData = renderStatesData[0];
|
||
var mat = material;
|
||
mat.blend = renderStateData.blend;
|
||
mat.cull = renderStateData.cull;
|
||
mat.depthTest = renderStateData.depthTest;
|
||
mat.depthWrite = renderStateData.depthWrite;
|
||
mat.blendSrc = renderStateData.srcBlend;
|
||
mat.blendDst = renderStateData.dstBlend;
|
||
break;
|
||
case "cull":
|
||
material.cull = props[key];
|
||
break;
|
||
case "blend":
|
||
material.blend = props[key];
|
||
break;
|
||
case "depthWrite":
|
||
material.depthWrite = props[key];
|
||
break;
|
||
case "srcBlend":
|
||
material.blendSrc = props[key];
|
||
break;
|
||
case "dstBlend":
|
||
material.blendDst = props[key];
|
||
break;
|
||
default:
|
||
material[key] = props[key];
|
||
}
|
||
}
|
||
break;
|
||
case "LAYAMATERIAL:03":
|
||
var i, n;
|
||
for (var key in props) {
|
||
switch (key) {
|
||
case "type":
|
||
case "name":
|
||
break;
|
||
case "defines":
|
||
var defineNames = props[key];
|
||
for (i = 0, n = defineNames.length; i < n; i++) {
|
||
var define = Shader3D.getDefineByName(defineNames[i]);
|
||
material._shaderValues.addDefine(define);
|
||
}
|
||
break;
|
||
case "textures":
|
||
var textures = props[key];
|
||
for (i = 0, n = textures.length; i < n; i++) {
|
||
var texture = textures[i];
|
||
var path = texture.path;
|
||
(path) && (material._shaderValues.setTexture(Shader3D.propertyNameToID(texture.name), Laya.Loader.getRes(path)));
|
||
}
|
||
break;
|
||
default:
|
||
var property = props[key];
|
||
var uniName = Shader3D.propertyNameToID(key);
|
||
if (!property.length) {
|
||
material._shaderValues.setNumber(uniName, props[key]);
|
||
}
|
||
else {
|
||
var vectorValue = property;
|
||
switch (vectorValue.length) {
|
||
case 2:
|
||
material._shaderValues.setVector2(uniName, new Vector2(vectorValue[0], vectorValue[1]));
|
||
break;
|
||
case 3:
|
||
material._shaderValues.setVector3(uniName, new Vector3(vectorValue[0], vectorValue[1], vectorValue[2]));
|
||
break;
|
||
case 4:
|
||
material._shaderValues.setVector(uniName, new Vector4(vectorValue[0], vectorValue[1], vectorValue[2], vectorValue[3]));
|
||
break;
|
||
default:
|
||
throw new Error("BaseMaterial:unkonwn color length.");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
default:
|
||
throw new Error("BaseMaterial:unkonwn version.");
|
||
}
|
||
return material;
|
||
}
|
||
get shaderData() {
|
||
return this._shaderValues;
|
||
}
|
||
get alphaTestValue() {
|
||
return this._shaderValues.getNumber(Material.ALPHATESTVALUE);
|
||
}
|
||
set alphaTestValue(value) {
|
||
this._shaderValues.setNumber(Material.ALPHATESTVALUE, value);
|
||
}
|
||
get alphaTest() {
|
||
return this.shaderData.hasDefine(Material.SHADERDEFINE_ALPHATEST);
|
||
}
|
||
set alphaTest(value) {
|
||
if (value)
|
||
this._shaderValues.addDefine(Material.SHADERDEFINE_ALPHATEST);
|
||
else
|
||
this._shaderValues.removeDefine(Material.SHADERDEFINE_ALPHATEST);
|
||
}
|
||
get depthWrite() {
|
||
return this._shaderValues.getBool(Material.DEPTH_WRITE);
|
||
}
|
||
set depthWrite(value) {
|
||
this._shaderValues.setBool(Material.DEPTH_WRITE, value);
|
||
}
|
||
get cull() {
|
||
return this._shaderValues.getInt(Material.CULL);
|
||
}
|
||
set cull(value) {
|
||
this._shaderValues.setInt(Material.CULL, value);
|
||
}
|
||
get blend() {
|
||
return this._shaderValues.getInt(Material.BLEND);
|
||
}
|
||
set blend(value) {
|
||
this._shaderValues.setInt(Material.BLEND, value);
|
||
}
|
||
get blendSrc() {
|
||
return this._shaderValues.getInt(Material.BLEND_SRC);
|
||
}
|
||
set blendSrc(value) {
|
||
this._shaderValues.setInt(Material.BLEND_SRC, value);
|
||
}
|
||
get blendDst() {
|
||
return this._shaderValues.getInt(Material.BLEND_DST);
|
||
}
|
||
set blendDst(value) {
|
||
this._shaderValues.setInt(Material.BLEND_DST, value);
|
||
}
|
||
get depthTest() {
|
||
return this._shaderValues.getInt(Material.DEPTH_TEST);
|
||
}
|
||
set depthTest(value) {
|
||
this._shaderValues.setInt(Material.DEPTH_TEST, value);
|
||
}
|
||
get MaterialProperty() {
|
||
let propertyMap = {};
|
||
var shaderValues = this._shaderValues.getData();
|
||
for (let key in shaderValues) {
|
||
propertyMap[Shader3D._propertyNameMap[parseInt(key)]] = shaderValues[key];
|
||
}
|
||
return propertyMap;
|
||
}
|
||
get MaterialDefine() {
|
||
let shaderDefineArray = new Array();
|
||
let defineData = this._shaderValues._defineDatas;
|
||
Shader3D._getNamesByDefineData(defineData, shaderDefineArray);
|
||
return shaderDefineArray;
|
||
}
|
||
_removeTetxureReference() {
|
||
var data = this._shaderValues.getData();
|
||
for (var k in data) {
|
||
var value = data[k];
|
||
if (value && value instanceof Laya.BaseTexture)
|
||
value._removeReference();
|
||
}
|
||
}
|
||
_disposeResource() {
|
||
if (this._referenceCount > 0)
|
||
this._removeTetxureReference();
|
||
this._shaderValues = null;
|
||
}
|
||
_addReference(count = 1) {
|
||
super._addReference(count);
|
||
var data = this._shaderValues.getData();
|
||
for (var k in data) {
|
||
var value = data[k];
|
||
if (value && value instanceof Laya.BaseTexture)
|
||
value._addReference();
|
||
}
|
||
}
|
||
_removeReference(count = 1) {
|
||
super._removeReference(count);
|
||
this._removeTetxureReference();
|
||
}
|
||
setShaderName(name) {
|
||
this._shader = Shader3D.find(name);
|
||
if (!this._shader)
|
||
throw new Error("BaseMaterial: unknown shader name.");
|
||
}
|
||
setShaderPropertyValue(name, value) {
|
||
this.shaderData.setValueData(Shader3D.propertyNameToID(name), value);
|
||
}
|
||
getShaderPropertyValue(name) {
|
||
return this.shaderData.getValueData(Shader3D.propertyNameToID(name));
|
||
}
|
||
cloneTo(destObject) {
|
||
var destBaseMaterial = destObject;
|
||
destBaseMaterial.name = this.name;
|
||
destBaseMaterial.renderQueue = this.renderQueue;
|
||
this._shaderValues.cloneTo(destBaseMaterial._shaderValues);
|
||
}
|
||
clone() {
|
||
var dest = new Material();
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
get _defineDatas() {
|
||
return this._shaderValues._defineDatas;
|
||
}
|
||
}
|
||
Material.MATERIAL = "MATERIAL";
|
||
Material.RENDERQUEUE_OPAQUE = 2000;
|
||
Material.RENDERQUEUE_ALPHATEST = 2450;
|
||
Material.RENDERQUEUE_TRANSPARENT = 3000;
|
||
Material.ALPHATESTVALUE = Shader3D.propertyNameToID("u_AlphaTestValue");
|
||
Material.CULL = Shader3D.propertyNameToID("s_Cull");
|
||
Material.BLEND = Shader3D.propertyNameToID("s_Blend");
|
||
Material.BLEND_SRC = Shader3D.propertyNameToID("s_BlendSrc");
|
||
Material.BLEND_DST = Shader3D.propertyNameToID("s_BlendDst");
|
||
Material.DEPTH_TEST = Shader3D.propertyNameToID("s_DepthTest");
|
||
Material.DEPTH_WRITE = Shader3D.propertyNameToID("s_DepthWrite");
|
||
|
||
class BaseMaterial {
|
||
static load(url, complete) {
|
||
Laya.Laya.loader.create(url, complete, null, Material.MATERIAL);
|
||
}
|
||
static __initDefine__() {
|
||
BaseMaterial.SHADERDEFINE_ALPHATEST = Material.SHADERDEFINE_ALPHATEST;
|
||
}
|
||
}
|
||
BaseMaterial.MATERIAL = "MATERIAL";
|
||
BaseMaterial.RENDERQUEUE_OPAQUE = 2000;
|
||
BaseMaterial.RENDERQUEUE_ALPHATEST = 2450;
|
||
BaseMaterial.RENDERQUEUE_TRANSPARENT = 3000;
|
||
BaseMaterial.ALPHATESTVALUE = Shader3D.propertyNameToID("u_AlphaTestValue");
|
||
|
||
class RenderState {
|
||
constructor() {
|
||
this.cull = RenderState.CULL_BACK;
|
||
this.blend = RenderState.BLEND_DISABLE;
|
||
this.srcBlend = RenderState.BLENDPARAM_ONE;
|
||
this.dstBlend = RenderState.BLENDPARAM_ZERO;
|
||
this.srcBlendRGB = RenderState.BLENDPARAM_ONE;
|
||
this.dstBlendRGB = RenderState.BLENDPARAM_ZERO;
|
||
this.srcBlendAlpha = RenderState.BLENDPARAM_ONE;
|
||
this.dstBlendAlpha = RenderState.BLENDPARAM_ZERO;
|
||
this.blendConstColor = new Vector4(1, 1, 1, 1);
|
||
this.blendEquation = RenderState.BLENDEQUATION_ADD;
|
||
this.blendEquationRGB = RenderState.BLENDEQUATION_ADD;
|
||
this.blendEquationAlpha = RenderState.BLENDEQUATION_ADD;
|
||
this.depthTest = RenderState.DEPTHTEST_LEQUAL;
|
||
this.depthWrite = true;
|
||
}
|
||
cloneTo(dest) {
|
||
var destState = dest;
|
||
destState.cull = this.cull;
|
||
destState.blend = this.blend;
|
||
destState.srcBlend = this.srcBlend;
|
||
destState.dstBlend = this.dstBlend;
|
||
destState.srcBlendRGB = this.srcBlendRGB;
|
||
destState.dstBlendRGB = this.dstBlendRGB;
|
||
destState.srcBlendAlpha = this.srcBlendAlpha;
|
||
destState.dstBlendAlpha = this.dstBlendAlpha;
|
||
this.blendConstColor.cloneTo(destState.blendConstColor);
|
||
destState.blendEquation = this.blendEquation;
|
||
destState.blendEquationRGB = this.blendEquationRGB;
|
||
destState.blendEquationAlpha = this.blendEquationAlpha;
|
||
destState.depthTest = this.depthTest;
|
||
destState.depthWrite = this.depthWrite;
|
||
}
|
||
clone() {
|
||
var dest = new RenderState();
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
}
|
||
RenderState.CULL_NONE = 0;
|
||
RenderState.CULL_FRONT = 1;
|
||
RenderState.CULL_BACK = 2;
|
||
RenderState.BLEND_DISABLE = 0;
|
||
RenderState.BLEND_ENABLE_ALL = 1;
|
||
RenderState.BLEND_ENABLE_SEPERATE = 2;
|
||
RenderState.BLENDPARAM_ZERO = 0;
|
||
RenderState.BLENDPARAM_ONE = 1;
|
||
RenderState.BLENDPARAM_SRC_COLOR = 0x0300;
|
||
RenderState.BLENDPARAM_ONE_MINUS_SRC_COLOR = 0x0301;
|
||
RenderState.BLENDPARAM_DST_COLOR = 0x0306;
|
||
RenderState.BLENDPARAM_ONE_MINUS_DST_COLOR = 0x0307;
|
||
RenderState.BLENDPARAM_SRC_ALPHA = 0x0302;
|
||
RenderState.BLENDPARAM_ONE_MINUS_SRC_ALPHA = 0x0303;
|
||
RenderState.BLENDPARAM_DST_ALPHA = 0x0304;
|
||
RenderState.BLENDPARAM_ONE_MINUS_DST_ALPHA = 0x0305;
|
||
RenderState.BLENDPARAM_SRC_ALPHA_SATURATE = 0x0308;
|
||
RenderState.BLENDEQUATION_ADD = 0x8006;
|
||
RenderState.BLENDEQUATION_SUBTRACT = 0x800A;
|
||
RenderState.BLENDEQUATION_REVERSE_SUBTRACT = 0x800B;
|
||
RenderState.DEPTHTEST_OFF = 0;
|
||
RenderState.DEPTHTEST_NEVER = 0x0200;
|
||
RenderState.DEPTHTEST_LESS = 0x0201;
|
||
RenderState.DEPTHTEST_EQUAL = 0x0202;
|
||
RenderState.DEPTHTEST_LEQUAL = 0x0203;
|
||
RenderState.DEPTHTEST_GREATER = 0x0204;
|
||
RenderState.DEPTHTEST_NOTEQUAL = 0x0205;
|
||
RenderState.DEPTHTEST_GEQUAL = 0x0206;
|
||
RenderState.DEPTHTEST_ALWAYS = 0x0207;
|
||
|
||
class BlinnPhongMaterial extends Material {
|
||
constructor() {
|
||
super();
|
||
this.setShaderName("BLINNPHONG");
|
||
this.albedoIntensity = 1.0;
|
||
var sv = this._shaderValues;
|
||
sv.setVector(BlinnPhongMaterial.ALBEDOCOLOR, new Vector4(1.0, 1.0, 1.0, 1.0));
|
||
sv.setVector(BlinnPhongMaterial.MATERIALSPECULAR, new Vector4(1.0, 1.0, 1.0, 1.0));
|
||
sv.setNumber(BlinnPhongMaterial.SHININESS, 0.078125);
|
||
sv.setNumber(Material.ALPHATESTVALUE, 0.5);
|
||
sv.setVector(BlinnPhongMaterial.TILINGOFFSET, new Vector4(1.0, 1.0, 0.0, 0.0));
|
||
this.albedoIntensity = 1.0;
|
||
this.renderMode = BlinnPhongMaterial.RENDERMODE_OPAQUE;
|
||
}
|
||
static __initDefine__() {
|
||
BlinnPhongMaterial.SHADERDEFINE_DIFFUSEMAP = Shader3D.getDefineByName("DIFFUSEMAP");
|
||
BlinnPhongMaterial.SHADERDEFINE_NORMALMAP = Shader3D.getDefineByName("NORMALMAP");
|
||
BlinnPhongMaterial.SHADERDEFINE_SPECULARMAP = Shader3D.getDefineByName("SPECULARMAP");
|
||
BlinnPhongMaterial.SHADERDEFINE_ENABLEVERTEXCOLOR = Shader3D.getDefineByName("ENABLEVERTEXCOLOR");
|
||
BlinnPhongMaterial.SHADERDEFINE_ENABLETRANSMISSION = Shader3D.getDefineByName("ENABLETRANSMISSION");
|
||
BlinnPhongMaterial.SHADERDEFINE_THICKNESSMAP = Shader3D.getDefineByName("THICKNESSMAP");
|
||
}
|
||
get _ColorR() {
|
||
return this.albedoColor.x;
|
||
}
|
||
set _ColorR(value) {
|
||
let albedoColor = this.albedoColor;
|
||
albedoColor.x = value;
|
||
this.albedoColor = albedoColor;
|
||
}
|
||
get _ColorG() {
|
||
return this.albedoColor.y;
|
||
}
|
||
set _ColorG(value) {
|
||
let albedoColor = this.albedoColor;
|
||
albedoColor.y = value;
|
||
this.albedoColor = albedoColor;
|
||
}
|
||
get _ColorB() {
|
||
return this.albedoColor.z;
|
||
}
|
||
set _ColorB(value) {
|
||
let albedoColor = this.albedoColor;
|
||
albedoColor.z = value;
|
||
this.albedoColor = albedoColor;
|
||
}
|
||
get _ColorA() {
|
||
return this.albedoColor.w;
|
||
}
|
||
set _ColorA(value) {
|
||
let albedoColor = this.albedoColor;
|
||
albedoColor.w = value;
|
||
this.albedoColor = albedoColor;
|
||
}
|
||
get _Color() {
|
||
return this._shaderValues.getVector(BlinnPhongMaterial.ALBEDOCOLOR);
|
||
}
|
||
set _Color(value) {
|
||
this.albedoColor = value;
|
||
}
|
||
get _SpecColorR() {
|
||
return this._shaderValues.getVector(BlinnPhongMaterial.MATERIALSPECULAR).x;
|
||
}
|
||
set _SpecColorR(value) {
|
||
this._shaderValues.getVector(BlinnPhongMaterial.MATERIALSPECULAR).x = value;
|
||
}
|
||
get _SpecColorG() {
|
||
return this._shaderValues.getVector(BlinnPhongMaterial.MATERIALSPECULAR).y;
|
||
}
|
||
set _SpecColorG(value) {
|
||
this._shaderValues.getVector(BlinnPhongMaterial.MATERIALSPECULAR).y = value;
|
||
}
|
||
get _SpecColorB() {
|
||
return this._shaderValues.getVector(BlinnPhongMaterial.MATERIALSPECULAR).z;
|
||
}
|
||
set _SpecColorB(value) {
|
||
this._shaderValues.getVector(BlinnPhongMaterial.MATERIALSPECULAR).z = value;
|
||
}
|
||
get _SpecColorA() {
|
||
return this._shaderValues.getVector(BlinnPhongMaterial.MATERIALSPECULAR).w;
|
||
}
|
||
set _SpecColorA(value) {
|
||
this._shaderValues.getVector(BlinnPhongMaterial.MATERIALSPECULAR).w = value;
|
||
}
|
||
get _SpecColor() {
|
||
return this._shaderValues.getVector(BlinnPhongMaterial.MATERIALSPECULAR);
|
||
}
|
||
set _SpecColor(value) {
|
||
this.specularColor = value;
|
||
}
|
||
get _Shininess() {
|
||
return this._shaderValues.getNumber(BlinnPhongMaterial.SHININESS);
|
||
}
|
||
set _Shininess(value) {
|
||
value = Math.max(0.0, Math.min(1.0, value));
|
||
this._shaderValues.setNumber(BlinnPhongMaterial.SHININESS, value);
|
||
}
|
||
get _MainTex_STX() {
|
||
return this._shaderValues.getVector(BlinnPhongMaterial.TILINGOFFSET).x;
|
||
}
|
||
set _MainTex_STX(x) {
|
||
var tilOff = this._shaderValues.getVector(BlinnPhongMaterial.TILINGOFFSET);
|
||
tilOff.x = x;
|
||
this.tilingOffset = tilOff;
|
||
}
|
||
get _MainTex_STY() {
|
||
return this._shaderValues.getVector(BlinnPhongMaterial.TILINGOFFSET).y;
|
||
}
|
||
set _MainTex_STY(y) {
|
||
var tilOff = this._shaderValues.getVector(BlinnPhongMaterial.TILINGOFFSET);
|
||
tilOff.y = y;
|
||
this.tilingOffset = tilOff;
|
||
}
|
||
get _MainTex_STZ() {
|
||
return this._shaderValues.getVector(BlinnPhongMaterial.TILINGOFFSET).z;
|
||
}
|
||
set _MainTex_STZ(z) {
|
||
var tilOff = this._shaderValues.getVector(BlinnPhongMaterial.TILINGOFFSET);
|
||
tilOff.z = z;
|
||
this.tilingOffset = tilOff;
|
||
}
|
||
get _MainTex_STW() {
|
||
return this._shaderValues.getVector(BlinnPhongMaterial.TILINGOFFSET).w;
|
||
}
|
||
set _MainTex_STW(w) {
|
||
var tilOff = this._shaderValues.getVector(BlinnPhongMaterial.TILINGOFFSET);
|
||
tilOff.w = w;
|
||
this.tilingOffset = tilOff;
|
||
}
|
||
get _MainTex_ST() {
|
||
return this._shaderValues.getVector(BlinnPhongMaterial.TILINGOFFSET);
|
||
}
|
||
set _MainTex_ST(value) {
|
||
this.tilingOffset = value;
|
||
}
|
||
get _Cutoff() {
|
||
return this.alphaTestValue;
|
||
}
|
||
set _Cutoff(value) {
|
||
this.alphaTestValue = value;
|
||
}
|
||
set renderMode(value) {
|
||
switch (value) {
|
||
case BlinnPhongMaterial.RENDERMODE_OPAQUE:
|
||
this.alphaTest = false;
|
||
this.renderQueue = Material.RENDERQUEUE_OPAQUE;
|
||
this.depthWrite = true;
|
||
this.cull = RenderState.CULL_BACK;
|
||
this.blend = RenderState.BLEND_DISABLE;
|
||
this.depthTest = RenderState.DEPTHTEST_LESS;
|
||
break;
|
||
case BlinnPhongMaterial.RENDERMODE_CUTOUT:
|
||
this.renderQueue = Material.RENDERQUEUE_ALPHATEST;
|
||
this.alphaTest = true;
|
||
this.depthWrite = true;
|
||
this.cull = RenderState.CULL_BACK;
|
||
this.blend = RenderState.BLEND_DISABLE;
|
||
this.depthTest = RenderState.DEPTHTEST_LESS;
|
||
break;
|
||
case BlinnPhongMaterial.RENDERMODE_TRANSPARENT:
|
||
this.renderQueue = Material.RENDERQUEUE_TRANSPARENT;
|
||
this.alphaTest = false;
|
||
this.depthWrite = false;
|
||
this.cull = RenderState.CULL_BACK;
|
||
this.blend = RenderState.BLEND_ENABLE_ALL;
|
||
this.blendSrc = RenderState.BLENDPARAM_SRC_ALPHA;
|
||
this.blendDst = RenderState.BLENDPARAM_ONE_MINUS_SRC_ALPHA;
|
||
this.depthTest = RenderState.DEPTHTEST_LESS;
|
||
break;
|
||
default:
|
||
throw new Error("Material:renderMode value error.");
|
||
}
|
||
}
|
||
get enableVertexColor() {
|
||
return this._shaderValues.hasDefine(BlinnPhongMaterial.SHADERDEFINE_ENABLEVERTEXCOLOR);
|
||
}
|
||
set enableVertexColor(value) {
|
||
if (value)
|
||
this._shaderValues.addDefine(BlinnPhongMaterial.SHADERDEFINE_ENABLEVERTEXCOLOR);
|
||
else
|
||
this._shaderValues.removeDefine(BlinnPhongMaterial.SHADERDEFINE_ENABLEVERTEXCOLOR);
|
||
}
|
||
get tilingOffsetX() {
|
||
return this._MainTex_STX;
|
||
}
|
||
set tilingOffsetX(x) {
|
||
this._MainTex_STX = x;
|
||
}
|
||
get tilingOffsetY() {
|
||
return this._MainTex_STY;
|
||
}
|
||
set tilingOffsetY(y) {
|
||
this._MainTex_STY = y;
|
||
}
|
||
get tilingOffsetZ() {
|
||
return this._MainTex_STZ;
|
||
}
|
||
set tilingOffsetZ(z) {
|
||
this._MainTex_STZ = z;
|
||
}
|
||
get tilingOffsetW() {
|
||
return this._MainTex_STW;
|
||
}
|
||
set tilingOffsetW(w) {
|
||
this._MainTex_STW = w;
|
||
}
|
||
get tilingOffset() {
|
||
return this._shaderValues.getVector(BlinnPhongMaterial.TILINGOFFSET);
|
||
}
|
||
set tilingOffset(value) {
|
||
if (value) {
|
||
this._shaderValues.setVector(BlinnPhongMaterial.TILINGOFFSET, value);
|
||
}
|
||
else {
|
||
this._shaderValues.getVector(BlinnPhongMaterial.TILINGOFFSET).setValue(1.0, 1.0, 0.0, 0.0);
|
||
}
|
||
}
|
||
get albedoColorR() {
|
||
return this._ColorR;
|
||
}
|
||
set albedoColorR(value) {
|
||
this._ColorR = value;
|
||
}
|
||
get albedoColorG() {
|
||
return this._ColorG;
|
||
}
|
||
set albedoColorG(value) {
|
||
this._ColorG = value;
|
||
}
|
||
get albedoColorB() {
|
||
return this._ColorB;
|
||
}
|
||
set albedoColorB(value) {
|
||
this._ColorB = value;
|
||
}
|
||
get albedoColorA() {
|
||
return this._ColorA;
|
||
}
|
||
set albedoColorA(value) {
|
||
this._ColorA = value;
|
||
}
|
||
get albedoColor() {
|
||
return this._shaderValues.getVector(BlinnPhongMaterial.ALBEDOCOLOR);
|
||
}
|
||
set albedoColor(value) {
|
||
this._shaderValues.setVector(BlinnPhongMaterial.ALBEDOCOLOR, value);
|
||
}
|
||
get albedoIntensity() {
|
||
return this._shaderValues.getNumber(BlinnPhongMaterial.AlbedoIntensity);
|
||
}
|
||
set albedoIntensity(value) {
|
||
this._shaderValues.setNumber(BlinnPhongMaterial.AlbedoIntensity, value);
|
||
}
|
||
get specularColorR() {
|
||
return this._SpecColorR;
|
||
}
|
||
set specularColorR(value) {
|
||
this._SpecColorR = value;
|
||
}
|
||
get specularColorG() {
|
||
return this._SpecColorG;
|
||
}
|
||
set specularColorG(value) {
|
||
this._SpecColorG = value;
|
||
}
|
||
get specularColorB() {
|
||
return this._SpecColorB;
|
||
}
|
||
set specularColorB(value) {
|
||
this._SpecColorB = value;
|
||
}
|
||
get specularColorA() {
|
||
return this._SpecColorA;
|
||
}
|
||
set specularColorA(value) {
|
||
this._SpecColorA = value;
|
||
}
|
||
get specularColor() {
|
||
return this._shaderValues.getVector(BlinnPhongMaterial.MATERIALSPECULAR);
|
||
}
|
||
set specularColor(value) {
|
||
this._shaderValues.setVector(BlinnPhongMaterial.MATERIALSPECULAR, value);
|
||
}
|
||
get shininess() {
|
||
return this._Shininess;
|
||
}
|
||
set shininess(value) {
|
||
this._Shininess = value;
|
||
}
|
||
get albedoTexture() {
|
||
return this._shaderValues.getTexture(BlinnPhongMaterial.ALBEDOTEXTURE);
|
||
}
|
||
set albedoTexture(value) {
|
||
if (value)
|
||
this._shaderValues.addDefine(BlinnPhongMaterial.SHADERDEFINE_DIFFUSEMAP);
|
||
else
|
||
this._shaderValues.removeDefine(BlinnPhongMaterial.SHADERDEFINE_DIFFUSEMAP);
|
||
this._shaderValues.setTexture(BlinnPhongMaterial.ALBEDOTEXTURE, value);
|
||
}
|
||
get normalTexture() {
|
||
return this._shaderValues.getTexture(BlinnPhongMaterial.NORMALTEXTURE);
|
||
}
|
||
set normalTexture(value) {
|
||
if (value)
|
||
this._shaderValues.addDefine(BlinnPhongMaterial.SHADERDEFINE_NORMALMAP);
|
||
else
|
||
this._shaderValues.removeDefine(BlinnPhongMaterial.SHADERDEFINE_NORMALMAP);
|
||
this._shaderValues.setTexture(BlinnPhongMaterial.NORMALTEXTURE, value);
|
||
}
|
||
get specularTexture() {
|
||
return this._shaderValues.getTexture(BlinnPhongMaterial.SPECULARTEXTURE);
|
||
}
|
||
set specularTexture(value) {
|
||
if (value)
|
||
this._shaderValues.addDefine(BlinnPhongMaterial.SHADERDEFINE_SPECULARMAP);
|
||
else
|
||
this._shaderValues.removeDefine(BlinnPhongMaterial.SHADERDEFINE_SPECULARMAP);
|
||
this._shaderValues.setTexture(BlinnPhongMaterial.SPECULARTEXTURE, value);
|
||
}
|
||
get enableTransmission() {
|
||
return this._shaderValues.hasDefine(BlinnPhongMaterial.SHADERDEFINE_ENABLETRANSMISSION);
|
||
}
|
||
set enableTransmission(value) {
|
||
if (value)
|
||
this._shaderValues.addDefine(BlinnPhongMaterial.SHADERDEFINE_ENABLETRANSMISSION);
|
||
else
|
||
this._shaderValues.removeDefine(BlinnPhongMaterial.SHADERDEFINE_ENABLETRANSMISSION);
|
||
}
|
||
get transmissionRate() {
|
||
return this._shaderValues.getNumber(BlinnPhongMaterial.TRANSMISSIONRATE);
|
||
}
|
||
set transmissionRata(value) {
|
||
this._shaderValues.setNumber(BlinnPhongMaterial.TRANSMISSIONRATE, value);
|
||
}
|
||
get backDiffuse() {
|
||
return this._shaderValues.getNumber(BlinnPhongMaterial.IBACKDIFFUSE);
|
||
}
|
||
set backDiffuse(value) {
|
||
this._shaderValues.setNumber(BlinnPhongMaterial.IBACKDIFFUSE, Math.max(value, 1.0));
|
||
}
|
||
get backScale() {
|
||
return this._shaderValues.getNumber(BlinnPhongMaterial.IBACKSCALE);
|
||
}
|
||
set backScale(value) {
|
||
this._shaderValues.setNumber(BlinnPhongMaterial.IBACKSCALE, value);
|
||
}
|
||
get thinknessTexture() {
|
||
return this._shaderValues.getTexture(BlinnPhongMaterial.THINKNESSTEXTURE);
|
||
}
|
||
set thinknessTexture(value) {
|
||
if (value)
|
||
this._shaderValues.addDefine(BlinnPhongMaterial.SHADERDEFINE_THICKNESSMAP);
|
||
else
|
||
this._shaderValues.removeDefine(BlinnPhongMaterial.SHADERDEFINE_THICKNESSMAP);
|
||
this._shaderValues.setTexture(BlinnPhongMaterial.THINKNESSTEXTURE, value);
|
||
}
|
||
get transmissionColor() {
|
||
return this._shaderValues.getVector(BlinnPhongMaterial.TRANSMISSIONCOLOR);
|
||
}
|
||
set transmissionColor(value) {
|
||
this._shaderValues.setVector(BlinnPhongMaterial.TRANSMISSIONCOLOR, value);
|
||
}
|
||
clone() {
|
||
var dest = new BlinnPhongMaterial();
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
cloneTo(destObject) {
|
||
super.cloneTo(destObject);
|
||
var destMaterial = destObject;
|
||
destMaterial.albedoIntensity = this.albedoIntensity;
|
||
destMaterial.enableVertexColor = this.enableVertexColor;
|
||
this.albedoColor.cloneTo(destMaterial.albedoColor);
|
||
}
|
||
}
|
||
BlinnPhongMaterial.RENDERMODE_OPAQUE = 0;
|
||
BlinnPhongMaterial.RENDERMODE_CUTOUT = 1;
|
||
BlinnPhongMaterial.RENDERMODE_TRANSPARENT = 2;
|
||
BlinnPhongMaterial.ALBEDOTEXTURE = Shader3D.propertyNameToID("u_DiffuseTexture");
|
||
BlinnPhongMaterial.NORMALTEXTURE = Shader3D.propertyNameToID("u_NormalTexture");
|
||
BlinnPhongMaterial.SPECULARTEXTURE = Shader3D.propertyNameToID("u_SpecularTexture");
|
||
BlinnPhongMaterial.ALBEDOCOLOR = Shader3D.propertyNameToID("u_DiffuseColor");
|
||
BlinnPhongMaterial.MATERIALSPECULAR = Shader3D.propertyNameToID("u_MaterialSpecular");
|
||
BlinnPhongMaterial.SHININESS = Shader3D.propertyNameToID("u_Shininess");
|
||
BlinnPhongMaterial.TILINGOFFSET = Shader3D.propertyNameToID("u_TilingOffset");
|
||
BlinnPhongMaterial.TRANSMISSIONRATE = Shader3D.propertyNameToID("u_TransmissionRate");
|
||
BlinnPhongMaterial.IBACKDIFFUSE = Shader3D.propertyNameToID("u_BackDiffuse");
|
||
BlinnPhongMaterial.IBACKSCALE = Shader3D.propertyNameToID("u_BackScale");
|
||
BlinnPhongMaterial.THINKNESSTEXTURE = Shader3D.propertyNameToID("u_ThinknessTexture");
|
||
BlinnPhongMaterial.TRANSMISSIONCOLOR = Shader3D.propertyNameToID("u_TransmissionColor");
|
||
BlinnPhongMaterial.AlbedoIntensity = Shader3D.propertyNameToID("u_AlbedoIntensity");
|
||
|
||
class EffectMaterial extends Material {
|
||
constructor() {
|
||
super();
|
||
this.setShaderName("Effect");
|
||
this._shaderValues.setVector(EffectMaterial.TILINGOFFSET, new Vector4(1.0, 1.0, 0.0, 0.0));
|
||
this._shaderValues.setVector(EffectMaterial.TINTCOLOR, new Vector4(1.0, 1.0, 1.0, 1.0));
|
||
this.renderMode = EffectMaterial.RENDERMODE_ADDTIVE;
|
||
}
|
||
static __initDefine__() {
|
||
EffectMaterial.SHADERDEFINE_MAINTEXTURE = Shader3D.getDefineByName("MAINTEXTURE");
|
||
EffectMaterial.SHADERDEFINE_ADDTIVEFOG = Shader3D.getDefineByName("ADDTIVEFOG");
|
||
}
|
||
get _TintColorR() {
|
||
return this.color.x;
|
||
}
|
||
set _TintColorR(value) {
|
||
let co = this.color;
|
||
co.x = value;
|
||
this.color = co;
|
||
}
|
||
get _TintColorG() {
|
||
return this.color.y;
|
||
}
|
||
set _TintColorG(value) {
|
||
let co = this.color;
|
||
co.y = value;
|
||
this.color = co;
|
||
}
|
||
get _TintColorB() {
|
||
return this.color.z;
|
||
}
|
||
set _TintColorB(value) {
|
||
let co = this.color;
|
||
co.z = value;
|
||
this.color = co;
|
||
}
|
||
get _TintColorA() {
|
||
return this.color.w;
|
||
}
|
||
set _TintColorA(value) {
|
||
let co = this.color;
|
||
co.w = value;
|
||
this.color = co;
|
||
}
|
||
get _TintColor() {
|
||
return this._shaderValues.getVector(EffectMaterial.TINTCOLOR);
|
||
}
|
||
set _TintColor(value) {
|
||
this.color = value;
|
||
}
|
||
get _MainTex_STX() {
|
||
return this._shaderValues.getVector(EffectMaterial.TILINGOFFSET).x;
|
||
}
|
||
set _MainTex_STX(x) {
|
||
var tilOff = this._shaderValues.getVector(EffectMaterial.TILINGOFFSET);
|
||
tilOff.x = x;
|
||
this.tilingOffset = tilOff;
|
||
}
|
||
get _MainTex_STY() {
|
||
return this._shaderValues.getVector(EffectMaterial.TILINGOFFSET).y;
|
||
}
|
||
set _MainTex_STY(y) {
|
||
var tilOff = this._shaderValues.getVector(EffectMaterial.TILINGOFFSET);
|
||
tilOff.y = y;
|
||
this.tilingOffset = tilOff;
|
||
}
|
||
get _MainTex_STZ() {
|
||
return this._shaderValues.getVector(EffectMaterial.TILINGOFFSET).z;
|
||
}
|
||
set _MainTex_STZ(z) {
|
||
var tilOff = this._shaderValues.getVector(EffectMaterial.TILINGOFFSET);
|
||
tilOff.z = z;
|
||
this.tilingOffset = tilOff;
|
||
}
|
||
get _MainTex_STW() {
|
||
return this._shaderValues.getVector(EffectMaterial.TILINGOFFSET).w;
|
||
}
|
||
set _MainTex_STW(w) {
|
||
var tilOff = this._shaderValues.getVector(EffectMaterial.TILINGOFFSET);
|
||
tilOff.w = w;
|
||
this.tilingOffset = tilOff;
|
||
}
|
||
get _MainTex_ST() {
|
||
return this._shaderValues.getVector(EffectMaterial.TILINGOFFSET);
|
||
}
|
||
set _MainTex_ST(value) {
|
||
this.tilingOffset = value;
|
||
}
|
||
set renderMode(value) {
|
||
switch (value) {
|
||
case EffectMaterial.RENDERMODE_ADDTIVE:
|
||
this.renderQueue = Material.RENDERQUEUE_TRANSPARENT;
|
||
this.alphaTest = false;
|
||
this.depthWrite = false;
|
||
this.cull = RenderState.CULL_NONE;
|
||
this.blend = RenderState.BLEND_ENABLE_ALL;
|
||
this.blendSrc = RenderState.BLENDPARAM_SRC_ALPHA;
|
||
this.blendDst = RenderState.BLENDPARAM_ONE;
|
||
this.depthTest = RenderState.DEPTHTEST_LESS;
|
||
this._shaderValues.addDefine(EffectMaterial.SHADERDEFINE_ADDTIVEFOG);
|
||
break;
|
||
case EffectMaterial.RENDERMODE_ALPHABLENDED:
|
||
this.renderQueue = Material.RENDERQUEUE_TRANSPARENT;
|
||
this.alphaTest = false;
|
||
this.depthWrite = false;
|
||
this.cull = RenderState.CULL_NONE;
|
||
this.blend = RenderState.BLEND_ENABLE_ALL;
|
||
this.blendSrc = RenderState.BLENDPARAM_SRC_ALPHA;
|
||
this.blendDst = RenderState.BLENDPARAM_ONE_MINUS_SRC_ALPHA;
|
||
this.depthTest = RenderState.DEPTHTEST_LESS;
|
||
this._shaderValues.removeDefine(EffectMaterial.SHADERDEFINE_ADDTIVEFOG);
|
||
break;
|
||
default:
|
||
throw new Error("MeshEffectMaterial : renderMode value error.");
|
||
}
|
||
}
|
||
get colorR() {
|
||
return this._TintColorR;
|
||
}
|
||
set colorR(value) {
|
||
this._TintColorR = value;
|
||
}
|
||
get colorG() {
|
||
return this._TintColorG;
|
||
}
|
||
set colorG(value) {
|
||
this._TintColorG = value;
|
||
}
|
||
get colorB() {
|
||
return this._TintColorB;
|
||
}
|
||
set colorB(value) {
|
||
this._TintColorB = value;
|
||
}
|
||
get colorA() {
|
||
return this._TintColorA;
|
||
}
|
||
set colorA(value) {
|
||
this._TintColorA = value;
|
||
}
|
||
get color() {
|
||
return this._shaderValues.getVector(EffectMaterial.TINTCOLOR);
|
||
}
|
||
set color(value) {
|
||
this._shaderValues.setVector(EffectMaterial.TINTCOLOR, value);
|
||
}
|
||
get texture() {
|
||
return this._shaderValues.getTexture(EffectMaterial.MAINTEXTURE);
|
||
}
|
||
set texture(value) {
|
||
if (value)
|
||
this._shaderValues.addDefine(EffectMaterial.SHADERDEFINE_MAINTEXTURE);
|
||
else
|
||
this._shaderValues.removeDefine(EffectMaterial.SHADERDEFINE_MAINTEXTURE);
|
||
this._shaderValues.setTexture(EffectMaterial.MAINTEXTURE, value);
|
||
}
|
||
get tilingOffsetX() {
|
||
return this._MainTex_STX;
|
||
}
|
||
set tilingOffsetX(x) {
|
||
this._MainTex_STX = x;
|
||
}
|
||
get tilingOffsetY() {
|
||
return this._MainTex_STY;
|
||
}
|
||
set tilingOffsetY(y) {
|
||
this._MainTex_STY = y;
|
||
}
|
||
get tilingOffsetZ() {
|
||
return this._MainTex_STZ;
|
||
}
|
||
set tilingOffsetZ(z) {
|
||
this._MainTex_STZ = z;
|
||
}
|
||
get tilingOffsetW() {
|
||
return this._MainTex_STW;
|
||
}
|
||
set tilingOffsetW(w) {
|
||
this._MainTex_STW = w;
|
||
}
|
||
get tilingOffset() {
|
||
return this._shaderValues.getVector(EffectMaterial.TILINGOFFSET);
|
||
}
|
||
set tilingOffset(value) {
|
||
if (value) {
|
||
this._shaderValues.setVector(EffectMaterial.TILINGOFFSET, value);
|
||
}
|
||
else {
|
||
this._shaderValues.getVector(EffectMaterial.TILINGOFFSET).setValue(1.0, 1.0, 0.0, 0.0);
|
||
}
|
||
}
|
||
clone() {
|
||
var dest = new EffectMaterial();
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
}
|
||
EffectMaterial.RENDERMODE_ADDTIVE = 0;
|
||
EffectMaterial.RENDERMODE_ALPHABLENDED = 1;
|
||
EffectMaterial.MAINTEXTURE = Shader3D.propertyNameToID("u_AlbedoTexture");
|
||
EffectMaterial.TINTCOLOR = Shader3D.propertyNameToID("u_AlbedoColor");
|
||
EffectMaterial.TILINGOFFSET = Shader3D.propertyNameToID("u_TilingOffset");
|
||
|
||
class ExtendTerrainMaterial extends Material {
|
||
constructor() {
|
||
super();
|
||
this.setShaderName("ExtendTerrain");
|
||
this.renderMode = ExtendTerrainMaterial.RENDERMODE_OPAQUE;
|
||
}
|
||
static __initDefine__() {
|
||
ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM1 = Shader3D.getDefineByName("ExtendTerrain_DETAIL_NUM1");
|
||
ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM2 = Shader3D.getDefineByName("ExtendTerrain_DETAIL_NUM2");
|
||
ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM3 = Shader3D.getDefineByName("ExtendTerrain_DETAIL_NUM3");
|
||
ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM4 = Shader3D.getDefineByName("ExtendTerrain_DETAIL_NUM4");
|
||
ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM5 = Shader3D.getDefineByName("ExtendTerrain_DETAIL_NUM5");
|
||
}
|
||
get splatAlphaTexture() {
|
||
return this._shaderValues.getTexture(ExtendTerrainMaterial.SPLATALPHATEXTURE);
|
||
}
|
||
set splatAlphaTexture(value) {
|
||
this._shaderValues.setTexture(ExtendTerrainMaterial.SPLATALPHATEXTURE, value);
|
||
}
|
||
get diffuseTexture1() {
|
||
return this._shaderValues.getTexture(ExtendTerrainMaterial.DIFFUSETEXTURE1);
|
||
}
|
||
set diffuseTexture1(value) {
|
||
this._shaderValues.setTexture(ExtendTerrainMaterial.DIFFUSETEXTURE1, value);
|
||
this._setDetailNum(1);
|
||
}
|
||
get diffuseTexture2() {
|
||
return this._shaderValues.getTexture(ExtendTerrainMaterial.DIFFUSETEXTURE2);
|
||
}
|
||
set diffuseTexture2(value) {
|
||
this._shaderValues.setTexture(ExtendTerrainMaterial.DIFFUSETEXTURE2, value);
|
||
this._setDetailNum(2);
|
||
}
|
||
get diffuseTexture3() {
|
||
return this._shaderValues.getTexture(ExtendTerrainMaterial.DIFFUSETEXTURE3);
|
||
}
|
||
set diffuseTexture3(value) {
|
||
this._shaderValues.setTexture(ExtendTerrainMaterial.DIFFUSETEXTURE3, value);
|
||
this._setDetailNum(3);
|
||
}
|
||
get diffuseTexture4() {
|
||
return this._shaderValues.getTexture(ExtendTerrainMaterial.DIFFUSETEXTURE4);
|
||
}
|
||
set diffuseTexture4(value) {
|
||
this._shaderValues.setTexture(ExtendTerrainMaterial.DIFFUSETEXTURE4, value);
|
||
this._setDetailNum(4);
|
||
}
|
||
get diffuseTexture5() {
|
||
return this._shaderValues.getTexture(ExtendTerrainMaterial.DIFFUSETEXTURE5);
|
||
}
|
||
set diffuseTexture5(value) {
|
||
this._shaderValues.setTexture(ExtendTerrainMaterial.DIFFUSETEXTURE5, value);
|
||
this._setDetailNum(5);
|
||
}
|
||
set diffuseScaleOffset1(scaleOffset1) {
|
||
this._shaderValues.setVector(ExtendTerrainMaterial.DIFFUSESCALEOFFSET1, scaleOffset1);
|
||
}
|
||
set diffuseScaleOffset2(scaleOffset2) {
|
||
this._shaderValues.setVector(ExtendTerrainMaterial.DIFFUSESCALEOFFSET2, scaleOffset2);
|
||
}
|
||
set diffuseScaleOffset3(scaleOffset3) {
|
||
this._shaderValues.setVector(ExtendTerrainMaterial.DIFFUSESCALEOFFSET3, scaleOffset3);
|
||
}
|
||
set diffuseScaleOffset4(scaleOffset4) {
|
||
this._shaderValues.setVector(ExtendTerrainMaterial.DIFFUSESCALEOFFSET4, scaleOffset4);
|
||
}
|
||
set diffuseScaleOffset5(scaleOffset5) {
|
||
this._shaderValues.setVector(ExtendTerrainMaterial.DIFFUSESCALEOFFSET5, scaleOffset5);
|
||
}
|
||
set renderMode(value) {
|
||
switch (value) {
|
||
case ExtendTerrainMaterial.RENDERMODE_OPAQUE:
|
||
this.renderQueue = Material.RENDERQUEUE_OPAQUE;
|
||
this.depthWrite = true;
|
||
this.cull = RenderState.CULL_BACK;
|
||
this.blend = RenderState.BLEND_DISABLE;
|
||
this.depthTest = RenderState.DEPTHTEST_LESS;
|
||
break;
|
||
case ExtendTerrainMaterial.RENDERMODE_TRANSPARENT:
|
||
this.renderQueue = Material.RENDERQUEUE_OPAQUE;
|
||
this.depthWrite = false;
|
||
this.cull = RenderState.CULL_BACK;
|
||
this.blend = RenderState.BLEND_ENABLE_ALL;
|
||
this.blendSrc = RenderState.BLENDPARAM_SRC_ALPHA;
|
||
this.blendDst = RenderState.BLENDPARAM_ONE_MINUS_SRC_ALPHA;
|
||
this.depthTest = RenderState.DEPTHTEST_LEQUAL;
|
||
break;
|
||
default:
|
||
throw new Error("ExtendTerrainMaterial:renderMode value error.");
|
||
}
|
||
}
|
||
_setDetailNum(value) {
|
||
switch (value) {
|
||
case 1:
|
||
this._shaderValues.addDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM1);
|
||
this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM2);
|
||
this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM3);
|
||
this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM4);
|
||
this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM5);
|
||
break;
|
||
case 2:
|
||
this._shaderValues.addDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM2);
|
||
this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM1);
|
||
this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM3);
|
||
this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM4);
|
||
this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM5);
|
||
break;
|
||
case 3:
|
||
this._shaderValues.addDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM3);
|
||
this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM1);
|
||
this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM2);
|
||
this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM4);
|
||
this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM5);
|
||
break;
|
||
case 4:
|
||
this._shaderValues.addDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM4);
|
||
this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM1);
|
||
this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM2);
|
||
this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM3);
|
||
this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM5);
|
||
break;
|
||
case 5:
|
||
this._shaderValues.addDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM5);
|
||
this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM1);
|
||
this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM2);
|
||
this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM3);
|
||
this._shaderValues.removeDefine(ExtendTerrainMaterial.SHADERDEFINE_DETAIL_NUM4);
|
||
break;
|
||
}
|
||
}
|
||
clone() {
|
||
var dest = new ExtendTerrainMaterial();
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
}
|
||
ExtendTerrainMaterial.RENDERMODE_OPAQUE = 1;
|
||
ExtendTerrainMaterial.RENDERMODE_TRANSPARENT = 2;
|
||
ExtendTerrainMaterial.SPLATALPHATEXTURE = Shader3D.propertyNameToID("u_SplatAlphaTexture");
|
||
ExtendTerrainMaterial.DIFFUSETEXTURE1 = Shader3D.propertyNameToID("u_DiffuseTexture1");
|
||
ExtendTerrainMaterial.DIFFUSETEXTURE2 = Shader3D.propertyNameToID("u_DiffuseTexture2");
|
||
ExtendTerrainMaterial.DIFFUSETEXTURE3 = Shader3D.propertyNameToID("u_DiffuseTexture3");
|
||
ExtendTerrainMaterial.DIFFUSETEXTURE4 = Shader3D.propertyNameToID("u_DiffuseTexture4");
|
||
ExtendTerrainMaterial.DIFFUSETEXTURE5 = Shader3D.propertyNameToID("u_DiffuseTexture5");
|
||
ExtendTerrainMaterial.DIFFUSESCALEOFFSET1 = Shader3D.propertyNameToID("u_DiffuseScaleOffset1");
|
||
ExtendTerrainMaterial.DIFFUSESCALEOFFSET2 = Shader3D.propertyNameToID("u_DiffuseScaleOffset2");
|
||
ExtendTerrainMaterial.DIFFUSESCALEOFFSET3 = Shader3D.propertyNameToID("u_DiffuseScaleOffset3");
|
||
ExtendTerrainMaterial.DIFFUSESCALEOFFSET4 = Shader3D.propertyNameToID("u_DiffuseScaleOffset4");
|
||
ExtendTerrainMaterial.DIFFUSESCALEOFFSET5 = Shader3D.propertyNameToID("u_DiffuseScaleOffset5");
|
||
|
||
(function (PBRRenderMode) {
|
||
PBRRenderMode[PBRRenderMode["Opaque"] = 0] = "Opaque";
|
||
PBRRenderMode[PBRRenderMode["Cutout"] = 1] = "Cutout";
|
||
PBRRenderMode[PBRRenderMode["Fade"] = 2] = "Fade";
|
||
PBRRenderMode[PBRRenderMode["Transparent"] = 3] = "Transparent";
|
||
})(exports.PBRRenderMode || (exports.PBRRenderMode = {}));
|
||
class PBRMaterial extends Material {
|
||
constructor() {
|
||
super();
|
||
this._shaderValues.setVector(PBRMaterial.ALBEDOCOLOR, new Vector4(1.0, 1.0, 1.0, 1.0));
|
||
this._shaderValues.setVector(PBRMaterial.EMISSIONCOLOR, new Vector4(1.0, 1.0, 1.0, 1.0));
|
||
this._shaderValues.setVector(PBRMaterial.TILINGOFFSET, new Vector4(1.0, 1.0, 0.0, 0.0));
|
||
this._shaderValues.setNumber(PBRMaterial.SMOOTHNESS, 0.5);
|
||
this._shaderValues.setNumber(PBRMaterial.SMOOTHNESSSCALE, 1.0);
|
||
this._shaderValues.setNumber(PBRMaterial.OCCLUSIONSTRENGTH, 1.0);
|
||
this._shaderValues.setNumber(PBRMaterial.NORMALSCALE, 1.0);
|
||
this._shaderValues.setNumber(PBRMaterial.PARALLAXSCALE, 0.001);
|
||
this._shaderValues.setNumber(Material.ALPHATESTVALUE, 0.5);
|
||
this.renderMode = exports.PBRRenderMode.Opaque;
|
||
}
|
||
static __init__() {
|
||
PBRMaterial.SHADERDEFINE_ALBEDOTEXTURE = Shader3D.getDefineByName("ALBEDOTEXTURE");
|
||
PBRMaterial.SHADERDEFINE_NORMALTEXTURE = Shader3D.getDefineByName("NORMALTEXTURE");
|
||
PBRMaterial.SHADERDEFINE_PARALLAXTEXTURE = Shader3D.getDefineByName("PARALLAXTEXTURE");
|
||
PBRMaterial.SHADERDEFINE_OCCLUSIONTEXTURE = Shader3D.getDefineByName("OCCLUSIONTEXTURE");
|
||
PBRMaterial.SHADERDEFINE_EMISSION = Shader3D.getDefineByName("EMISSION");
|
||
PBRMaterial.SHADERDEFINE_EMISSIONTEXTURE = Shader3D.getDefineByName("EMISSIONTEXTURE");
|
||
PBRMaterial.SHADERDEFINE_TRANSPARENTBLEND = Shader3D.getDefineByName("TRANSPARENTBLEND");
|
||
PBRMaterial.SHADERDEFINE_LAYA_PBR_BRDF_HIGH = Shader3D.getDefineByName("LAYA_PBR_BRDF_HIGH");
|
||
PBRMaterial.SHADERDEFINE_LAYA_PBR_BRDF_LOW = Shader3D.getDefineByName("LAYA_PBR_BRDF_LOW");
|
||
}
|
||
get albedoColor() {
|
||
return this._shaderValues.getVector(PBRMaterial.ALBEDOCOLOR);
|
||
}
|
||
set albedoColor(value) {
|
||
this._shaderValues.setVector(PBRMaterial.ALBEDOCOLOR, value);
|
||
}
|
||
get albedoTexture() {
|
||
return this._shaderValues.getTexture(PBRMaterial.ALBEDOTEXTURE);
|
||
}
|
||
set albedoTexture(value) {
|
||
if (value)
|
||
this._shaderValues.addDefine(PBRMaterial.SHADERDEFINE_ALBEDOTEXTURE);
|
||
else
|
||
this._shaderValues.removeDefine(PBRMaterial.SHADERDEFINE_ALBEDOTEXTURE);
|
||
this._shaderValues.setTexture(PBRMaterial.ALBEDOTEXTURE, value);
|
||
}
|
||
get normalTexture() {
|
||
return this._shaderValues.getTexture(PBRMaterial.NORMALTEXTURE);
|
||
}
|
||
set normalTexture(value) {
|
||
if (value) {
|
||
this._shaderValues.addDefine(PBRMaterial.SHADERDEFINE_NORMALTEXTURE);
|
||
}
|
||
else {
|
||
this._shaderValues.removeDefine(PBRMaterial.SHADERDEFINE_NORMALTEXTURE);
|
||
}
|
||
this._shaderValues.setTexture(PBRMaterial.NORMALTEXTURE, value);
|
||
}
|
||
get normalTextureScale() {
|
||
return this._shaderValues.getNumber(PBRMaterial.NORMALSCALE);
|
||
}
|
||
set normalTextureScale(value) {
|
||
this._shaderValues.setNumber(PBRMaterial.NORMALSCALE, value);
|
||
}
|
||
get parallaxTexture() {
|
||
return this._shaderValues.getTexture(PBRMaterial.PARALLAXTEXTURE);
|
||
}
|
||
set parallaxTexture(value) {
|
||
if (value)
|
||
this._shaderValues.addDefine(PBRMaterial.SHADERDEFINE_PARALLAXTEXTURE);
|
||
else
|
||
this._shaderValues.removeDefine(PBRMaterial.SHADERDEFINE_PARALLAXTEXTURE);
|
||
this._shaderValues.setTexture(PBRMaterial.PARALLAXTEXTURE, value);
|
||
}
|
||
get parallaxTextureScale() {
|
||
return this._shaderValues.getNumber(PBRMaterial.PARALLAXSCALE);
|
||
}
|
||
set parallaxTextureScale(value) {
|
||
this._shaderValues.setNumber(PBRMaterial.PARALLAXSCALE, Math.max(0.005, Math.min(0.08, value)));
|
||
}
|
||
get occlusionTexture() {
|
||
return this._shaderValues.getTexture(PBRMaterial.OCCLUSIONTEXTURE);
|
||
}
|
||
set occlusionTexture(value) {
|
||
if (value)
|
||
this._shaderValues.addDefine(PBRMaterial.SHADERDEFINE_OCCLUSIONTEXTURE);
|
||
else
|
||
this._shaderValues.removeDefine(PBRMaterial.SHADERDEFINE_OCCLUSIONTEXTURE);
|
||
this._shaderValues.setTexture(PBRMaterial.OCCLUSIONTEXTURE, value);
|
||
}
|
||
get occlusionTextureStrength() {
|
||
return this._shaderValues.getNumber(PBRMaterial.OCCLUSIONSTRENGTH);
|
||
}
|
||
set occlusionTextureStrength(value) {
|
||
this._shaderValues.setNumber(PBRMaterial.OCCLUSIONSTRENGTH, Math.max(0.0, Math.min(1.0, value)));
|
||
}
|
||
get smoothness() {
|
||
return this._shaderValues.getNumber(PBRMaterial.SMOOTHNESS);
|
||
}
|
||
set smoothness(value) {
|
||
this._shaderValues.setNumber(PBRMaterial.SMOOTHNESS, Math.max(0.0, Math.min(1.0, value)));
|
||
}
|
||
get smoothnessTextureScale() {
|
||
return this._shaderValues.getNumber(PBRMaterial.SMOOTHNESSSCALE);
|
||
}
|
||
set smoothnessTextureScale(value) {
|
||
this._shaderValues.setNumber(PBRMaterial.SMOOTHNESSSCALE, Math.max(0.0, Math.min(1.0, value)));
|
||
}
|
||
get enableEmission() {
|
||
return this._shaderValues.hasDefine(PBRMaterial.SHADERDEFINE_EMISSION);
|
||
}
|
||
set enableEmission(value) {
|
||
if (value)
|
||
this._shaderValues.addDefine(PBRMaterial.SHADERDEFINE_EMISSION);
|
||
else
|
||
this._shaderValues.removeDefine(PBRMaterial.SHADERDEFINE_EMISSION);
|
||
}
|
||
get emissionColor() {
|
||
return this._shaderValues.getVector(PBRMaterial.EMISSIONCOLOR);
|
||
}
|
||
set emissionColor(value) {
|
||
this._shaderValues.setVector(PBRMaterial.EMISSIONCOLOR, value);
|
||
}
|
||
get emissionTexture() {
|
||
return this._shaderValues.getTexture(PBRMaterial.EMISSIONTEXTURE);
|
||
}
|
||
set emissionTexture(value) {
|
||
if (value)
|
||
this._shaderValues.addDefine(PBRMaterial.SHADERDEFINE_EMISSIONTEXTURE);
|
||
else
|
||
this._shaderValues.removeDefine(PBRMaterial.SHADERDEFINE_EMISSIONTEXTURE);
|
||
this._shaderValues.setTexture(PBRMaterial.EMISSIONTEXTURE, value);
|
||
}
|
||
get tilingOffset() {
|
||
return this._shaderValues.getVector(PBRMaterial.TILINGOFFSET);
|
||
}
|
||
set tilingOffset(value) {
|
||
if (value) {
|
||
this._shaderValues.setVector(PBRMaterial.TILINGOFFSET, value);
|
||
}
|
||
else {
|
||
this._shaderValues.getVector(PBRMaterial.TILINGOFFSET).setValue(1.0, 1.0, 0.0, 0.0);
|
||
}
|
||
}
|
||
set renderMode(value) {
|
||
switch (value) {
|
||
case exports.PBRRenderMode.Opaque:
|
||
this.alphaTest = false;
|
||
this.renderQueue = Material.RENDERQUEUE_OPAQUE;
|
||
this.depthWrite = true;
|
||
this.cull = RenderState.CULL_BACK;
|
||
this.blend = RenderState.BLEND_DISABLE;
|
||
this.depthTest = RenderState.DEPTHTEST_LESS;
|
||
this._shaderValues.removeDefine(PBRMaterial.SHADERDEFINE_TRANSPARENTBLEND);
|
||
break;
|
||
case exports.PBRRenderMode.Cutout:
|
||
this.renderQueue = Material.RENDERQUEUE_ALPHATEST;
|
||
this.alphaTest = true;
|
||
this.depthWrite = true;
|
||
this.cull = RenderState.CULL_BACK;
|
||
this.blend = RenderState.BLEND_DISABLE;
|
||
this.depthTest = RenderState.DEPTHTEST_LESS;
|
||
this._shaderValues.removeDefine(PBRMaterial.SHADERDEFINE_TRANSPARENTBLEND);
|
||
break;
|
||
case exports.PBRRenderMode.Fade:
|
||
this.renderQueue = Material.RENDERQUEUE_TRANSPARENT;
|
||
this.alphaTest = false;
|
||
this.depthWrite = false;
|
||
this.cull = RenderState.CULL_BACK;
|
||
this.blend = RenderState.BLEND_ENABLE_ALL;
|
||
this.blendSrc = RenderState.BLENDPARAM_SRC_ALPHA;
|
||
this.blendDst = RenderState.BLENDPARAM_ONE_MINUS_SRC_ALPHA;
|
||
this.depthTest = RenderState.DEPTHTEST_LESS;
|
||
this._shaderValues.removeDefine(PBRMaterial.SHADERDEFINE_TRANSPARENTBLEND);
|
||
break;
|
||
case exports.PBRRenderMode.Transparent:
|
||
this.renderQueue = Material.RENDERQUEUE_TRANSPARENT;
|
||
this.alphaTest = false;
|
||
this.depthWrite = false;
|
||
this.cull = RenderState.CULL_BACK;
|
||
this.blend = RenderState.BLEND_ENABLE_ALL;
|
||
this.blendSrc = RenderState.BLENDPARAM_ONE;
|
||
this.blendDst = RenderState.BLENDPARAM_ONE_MINUS_SRC_ALPHA;
|
||
this.depthTest = RenderState.DEPTHTEST_LESS;
|
||
this._shaderValues.addDefine(PBRMaterial.SHADERDEFINE_TRANSPARENTBLEND);
|
||
break;
|
||
default:
|
||
throw new Error("PBRMaterial:unknown renderMode value.");
|
||
}
|
||
}
|
||
}
|
||
PBRMaterial.ALBEDOTEXTURE = Shader3D.propertyNameToID("u_AlbedoTexture");
|
||
PBRMaterial.ALBEDOCOLOR = Shader3D.propertyNameToID("u_AlbedoColor");
|
||
PBRMaterial.TILINGOFFSET = Shader3D.propertyNameToID("u_TilingOffset");
|
||
PBRMaterial.NORMALTEXTURE = Shader3D.propertyNameToID("u_NormalTexture");
|
||
PBRMaterial.NORMALSCALE = Shader3D.propertyNameToID("u_NormalScale");
|
||
PBRMaterial.SMOOTHNESS = Shader3D.propertyNameToID("u_Smoothness");
|
||
PBRMaterial.SMOOTHNESSSCALE = Shader3D.propertyNameToID("u_SmoothnessScale");
|
||
PBRMaterial.OCCLUSIONTEXTURE = Shader3D.propertyNameToID("u_OcclusionTexture");
|
||
PBRMaterial.OCCLUSIONSTRENGTH = Shader3D.propertyNameToID("u_occlusionStrength");
|
||
PBRMaterial.PARALLAXTEXTURE = Shader3D.propertyNameToID("u_ParallaxTexture");
|
||
PBRMaterial.PARALLAXSCALE = Shader3D.propertyNameToID("u_ParallaxScale");
|
||
PBRMaterial.EMISSIONTEXTURE = Shader3D.propertyNameToID("u_EmissionTexture");
|
||
PBRMaterial.EMISSIONCOLOR = Shader3D.propertyNameToID("u_EmissionColor");
|
||
PBRMaterial.renderQuality = exports.PBRRenderQuality.High;
|
||
|
||
var PBRPS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n\tprecision highp int;\r\n#else\r\n\tprecision mediump float;\r\n\tprecision mediump int;\r\n#endif\r\n\r\n#define SETUP_BRDF_INPUT specularSetup\r\n\r\n#include \"Lighting.glsl\";\r\n#include \"PBRFSInput.glsl\";\r\n#include \"LayaPBRBRDF.glsl\";\r\n#include \"GlobalIllumination.glsl\";\r\n#include \"Shadow.glsl\"\r\n#include \"PBRCore.glsl\";\r\n\r\nvoid main()\r\n{\r\n\tfragmentForward();\r\n}";
|
||
|
||
var PBRVS = "#include \"PBRVSInput.glsl\";\r\n#include \"Lighting.glsl\";\r\n#include \"PBRVertex.glsl\";\r\n\r\nvoid main()\r\n{\r\n\tvertexForward();\r\n\tgl_Position=remapGLPositionZ(gl_Position);\r\n}";
|
||
|
||
var PBRShadowCasterPS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n\tprecision highp int;\r\n#else\r\n\tprecision mediump float;\r\n\tprecision mediump int;\r\n#endif\r\n\r\n#include \"ShadowCasterFS.glsl\"\r\n\r\nvoid main()\r\n{\r\n\tgl_FragColor=shadowCasterFragment();\r\n}";
|
||
|
||
var PBRShadowCasterVS = "#include \"ShadowCasterVS.glsl\"\r\n\r\nvoid main()\r\n{\r\n\tvec4 positionCS = shadowCasterVertex();\r\n\tgl_Position=remapGLPositionZ(positionCS);\r\n}";
|
||
|
||
var DepthNormalsTextureVS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n\tprecision highp int;\r\n#else\r\n\tprecision mediump float;\r\n\tprecision mediump int;\r\n#endif\r\n\r\n#include \"Lighting.glsl\";\r\n#include \"LayaUtile.glsl\"\r\n\r\nattribute vec4 a_Position;\r\nattribute vec3 a_Normal;\r\n\r\n#ifdef BONE\r\n\tconst int c_MaxBoneCount = 24;\r\n\tattribute vec4 a_BoneIndices;\r\n\tattribute vec4 a_BoneWeights;\r\n\tuniform mat4 u_Bones[c_MaxBoneCount];\r\n#endif\r\n\r\n#ifdef GPU_INSTANCE\r\n\tattribute mat4 a_WorldMat;\r\n#else\r\n\tuniform mat4 u_WorldMat;\r\n#endif\r\nuniform mat4 u_View;\r\nuniform mat4 u_ViewProjection;\r\nuniform vec4 u_ProjectionParams;\r\n\r\n//传入法线\r\nvarying vec4 depthNormals;\r\n\r\n\r\nvec4 depthNormalsVertex()\r\n{\r\n\tmat4 worldMat;\r\n\t#ifdef GPU_INSTANCE\r\n\t\tworldMat = a_WorldMat;\r\n\t#else\r\n\t\tworldMat = u_WorldMat;\r\n\t#endif\r\n\t\r\n\t#ifdef BONE\r\n\t\tmat4 skinTransform;\r\n\t \t#ifdef SIMPLEBONE\r\n\t\t\tfloat currentPixelPos;\r\n\t\t\t#ifdef GPU_INSTANCE\r\n\t\t\t\tcurrentPixelPos = a_SimpleTextureParams.x+a_SimpleTextureParams.y;\r\n\t\t\t#else\r\n\t\t\t\tcurrentPixelPos = u_SimpleAnimatorParams.x+u_SimpleAnimatorParams.y;\r\n\t\t\t#endif\r\n\t\t\tfloat offset = 1.0/u_SimpleAnimatorTextureSize;\r\n\t\t\tskinTransform = loadMatFromTexture(currentPixelPos,int(a_BoneIndices.x),offset) * a_BoneWeights.x;\r\n\t\t\tskinTransform += loadMatFromTexture(currentPixelPos,int(a_BoneIndices.y),offset) * a_BoneWeights.y;\r\n\t\t\tskinTransform += loadMatFromTexture(currentPixelPos,int(a_BoneIndices.z),offset) * a_BoneWeights.z;\r\n\t\t\tskinTransform += loadMatFromTexture(currentPixelPos,int(a_BoneIndices.w),offset) * a_BoneWeights.w;\r\n\t\t#else\r\n\t\t\tskinTransform = u_Bones[int(a_BoneIndices.x)] * a_BoneWeights.x;\r\n\t\t\tskinTransform += u_Bones[int(a_BoneIndices.y)] * a_BoneWeights.y;\r\n\t\t\tskinTransform += u_Bones[int(a_BoneIndices.z)] * a_BoneWeights.z;\r\n\t\t\tskinTransform += u_Bones[int(a_BoneIndices.w)] * a_BoneWeights.w;\r\n\t\t#endif\r\n\t\tworldMat = worldMat * skinTransform;\r\n\t#endif\r\n\r\n\tvec4 positionWS = worldMat * a_Position;\r\n\r\n\tmat3 worldInvMat;\r\n\t#ifdef BONE\r\n\t\tworldInvMat=INVERSE_MAT(mat3(worldMat*skinTransform));\r\n\t#else\r\n\t\tworldInvMat=INVERSE_MAT(mat3(worldMat));\r\n\t#endif \r\n\r\n\tvec3 normalWS = normalize(a_Normal*worldInvMat);//if no normalize will cause precision problem\r\n\t//depthNormals.xyz = normalWS;\r\n\t//存储View空间法线\r\n\tvec3 normalVS = mat3(u_View) * normalWS;\r\n\tdepthNormals.xyz = normalVS;\r\n\t\r\n\tvec4 positionCS = u_ViewProjection * positionWS;\r\n\tdepthNormals.w = (positionCS.z * 2.0 - positionCS.w)*u_ProjectionParams.w;\r\n\t\r\n return positionCS;\r\n}\r\n\r\nvoid main()\r\n{\r\n\tvec4 positionCS = depthNormalsVertex();\r\n\tgl_Position=remapGLPositionZ(positionCS);\r\n}";
|
||
|
||
var DepthNormalsTextureFS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n\tprecision highp int;\r\n#else\r\n\tprecision mediump float;\r\n\tprecision mediump int;\r\n#endif\r\n#include \"DepthNormalUtil.glsl\";\r\n\r\nvarying vec4 depthNormals;\r\n\r\nvoid main()\r\n{\r\n\tgl_FragColor=depthNormalsFragment(depthNormals);\r\n}";
|
||
|
||
class ShaderVariable {
|
||
constructor() {
|
||
this.textureID = -1;
|
||
}
|
||
}
|
||
|
||
class ShaderInstance extends Laya.Resource {
|
||
constructor(vs, ps, attributeMap, uniformMap, shaderPass) {
|
||
super();
|
||
this._stateParamsMap = [];
|
||
this._uploadMark = -1;
|
||
this._uploadRenderType = -1;
|
||
this._vs = vs;
|
||
this._ps = ps;
|
||
this._attributeMap = attributeMap;
|
||
this._uniformMap = uniformMap;
|
||
this._shaderPass = shaderPass;
|
||
this._globaluniformMap = {};
|
||
this._create();
|
||
this.lock = true;
|
||
}
|
||
_create() {
|
||
var gl = Laya.LayaGL.instance;
|
||
this._program = gl.createProgram();
|
||
this._vshader = this._createShader(gl, this._vs, gl.VERTEX_SHADER);
|
||
this._pshader = this._createShader(gl, this._ps, gl.FRAGMENT_SHADER);
|
||
gl.attachShader(this._program, this._vshader);
|
||
gl.attachShader(this._program, this._pshader);
|
||
for (var k in this._attributeMap)
|
||
gl.bindAttribLocation(this._program, this._attributeMap[k], k);
|
||
gl.linkProgram(this._program);
|
||
if (!Laya.Render.isConchApp && Shader3D.debugMode && !gl.getProgramParameter(this._program, gl.LINK_STATUS))
|
||
throw gl.getProgramInfoLog(this._program);
|
||
var sceneParms = [];
|
||
var cameraParms = [];
|
||
var spriteParms = [];
|
||
var materialParms = [];
|
||
var customParms = [];
|
||
this._customUniformParamsMap = [];
|
||
var nUniformNum = gl.getProgramParameter(this._program, gl.ACTIVE_UNIFORMS);
|
||
Laya.WebGLContext.useProgram(gl, this._program);
|
||
this._curActTexIndex = 0;
|
||
var one, i, n;
|
||
for (i = 0; i < nUniformNum; i++) {
|
||
var uniformData = gl.getActiveUniform(this._program, i);
|
||
var uniName = uniformData.name;
|
||
one = new ShaderVariable();
|
||
one.location = gl.getUniformLocation(this._program, uniName);
|
||
if (uniName.indexOf('[0]') > 0) {
|
||
one.name = uniName = uniName.substr(0, uniName.length - 3);
|
||
one.isArray = true;
|
||
}
|
||
else {
|
||
one.name = uniName;
|
||
one.isArray = false;
|
||
}
|
||
one.type = uniformData.type;
|
||
this._addShaderUnifiormFun(one);
|
||
var uniformPeriod = this._uniformMap[uniName];
|
||
if (uniformPeriod != null) {
|
||
one.dataOffset = Shader3D.propertyNameToID(uniName);
|
||
switch (uniformPeriod) {
|
||
case Shader3D.PERIOD_CUSTOM:
|
||
customParms.push(one);
|
||
break;
|
||
case Shader3D.PERIOD_MATERIAL:
|
||
materialParms.push(one);
|
||
break;
|
||
case Shader3D.PERIOD_SPRITE:
|
||
spriteParms.push(one);
|
||
break;
|
||
case Shader3D.PERIOD_CAMERA:
|
||
cameraParms.push(one);
|
||
break;
|
||
case Shader3D.PERIOD_SCENE:
|
||
sceneParms.push(one);
|
||
break;
|
||
default:
|
||
throw new Error("Shader3D: period is unkonw.");
|
||
}
|
||
}
|
||
else {
|
||
one.dataOffset = Shader3D.propertyNameToID(uniName);
|
||
this._globaluniformMap[uniName] = Shader3D.PERIOD_SCENE;
|
||
sceneParms.push(one);
|
||
}
|
||
}
|
||
this._sceneUniformParamsMap = Laya.LayaGL.instance.createCommandEncoder(sceneParms.length * 4 * 5 + 4, 64, true);
|
||
for (i = 0, n = sceneParms.length; i < n; i++)
|
||
this._sceneUniformParamsMap.addShaderUniform(sceneParms[i]);
|
||
this._cameraUniformParamsMap = Laya.LayaGL.instance.createCommandEncoder(cameraParms.length * 4 * 5 + 4, 64, true);
|
||
for (i = 0, n = cameraParms.length; i < n; i++)
|
||
this._cameraUniformParamsMap.addShaderUniform(cameraParms[i]);
|
||
this._spriteUniformParamsMap = Laya.LayaGL.instance.createCommandEncoder(spriteParms.length * 4 * 5 + 4, 64, true);
|
||
for (i = 0, n = spriteParms.length; i < n; i++)
|
||
this._spriteUniformParamsMap.addShaderUniform(spriteParms[i]);
|
||
this._materialUniformParamsMap = Laya.LayaGL.instance.createCommandEncoder(materialParms.length * 4 * 5 + 4, 64, true);
|
||
for (i = 0, n = materialParms.length; i < n; i++)
|
||
this._materialUniformParamsMap.addShaderUniform(materialParms[i]);
|
||
this._customUniformParamsMap.length = customParms.length;
|
||
for (i = 0, n = customParms.length; i < n; i++) {
|
||
var custom = customParms[i];
|
||
this._customUniformParamsMap[custom.dataOffset] = custom;
|
||
}
|
||
var stateMap = this._shaderPass._stateMap;
|
||
for (var s in stateMap)
|
||
this._stateParamsMap[stateMap[s]] = Shader3D.propertyNameToID(s);
|
||
}
|
||
_getRenderState(shaderDatas, stateIndex) {
|
||
var stateID = this._stateParamsMap[stateIndex];
|
||
if (stateID == null)
|
||
return null;
|
||
else
|
||
return shaderDatas[stateID];
|
||
}
|
||
_disposeResource() {
|
||
Laya.LayaGL.instance.deleteShader(this._vshader);
|
||
Laya.LayaGL.instance.deleteShader(this._pshader);
|
||
Laya.LayaGL.instance.deleteProgram(this._program);
|
||
this._vshader = this._pshader = this._program = null;
|
||
this._setGPUMemory(0);
|
||
this._curActTexIndex = 0;
|
||
}
|
||
_addShaderUnifiormFun(one) {
|
||
var gl = Laya.LayaGL.instance;
|
||
one.caller = this;
|
||
var isArray = one.isArray;
|
||
switch (one.type) {
|
||
case gl.BOOL:
|
||
one.fun = this._uniform1i;
|
||
one.uploadedValue = new Array(1);
|
||
break;
|
||
case gl.INT:
|
||
one.fun = isArray ? this._uniform1iv : this._uniform1i;
|
||
one.uploadedValue = new Array(1);
|
||
break;
|
||
case gl.FLOAT:
|
||
one.fun = isArray ? this._uniform1fv : this._uniform1f;
|
||
one.uploadedValue = new Array(1);
|
||
break;
|
||
case gl.FLOAT_VEC2:
|
||
one.fun = isArray ? this._uniform_vec2v : this._uniform_vec2;
|
||
one.uploadedValue = new Array(2);
|
||
break;
|
||
case gl.FLOAT_VEC3:
|
||
one.fun = isArray ? this._uniform_vec3v : this._uniform_vec3;
|
||
one.uploadedValue = new Array(3);
|
||
break;
|
||
case gl.FLOAT_VEC4:
|
||
one.fun = isArray ? this._uniform_vec4v : this._uniform_vec4;
|
||
one.uploadedValue = new Array(4);
|
||
break;
|
||
case gl.FLOAT_MAT2:
|
||
one.fun = this._uniformMatrix2fv;
|
||
break;
|
||
case gl.FLOAT_MAT3:
|
||
one.fun = this._uniformMatrix3fv;
|
||
break;
|
||
case gl.FLOAT_MAT4:
|
||
one.fun = isArray ? this._uniformMatrix4fv : this._uniformMatrix4f;
|
||
break;
|
||
case gl.SAMPLER_2D:
|
||
case gl.SAMPLER_2D_SHADOW:
|
||
gl.uniform1i(one.location, this._curActTexIndex);
|
||
one.textureID = Laya.WebGLContext._glTextureIDs[this._curActTexIndex++];
|
||
one.fun = this._uniform_sampler2D;
|
||
break;
|
||
case 0x8b5f:
|
||
gl.uniform1i(one.location, this._curActTexIndex);
|
||
one.textureID = Laya.WebGLContext._glTextureIDs[this._curActTexIndex++];
|
||
one.fun = this._uniform_sampler3D;
|
||
break;
|
||
case gl.SAMPLER_CUBE:
|
||
gl.uniform1i(one.location, this._curActTexIndex);
|
||
one.textureID = Laya.WebGLContext._glTextureIDs[this._curActTexIndex++];
|
||
one.fun = this._uniform_samplerCube;
|
||
break;
|
||
default:
|
||
throw new Error("compile shader err!");
|
||
}
|
||
}
|
||
_createShader(gl, str, type) {
|
||
var shader = gl.createShader(type);
|
||
gl.shaderSource(shader, str);
|
||
gl.compileShader(shader);
|
||
if (Shader3D.debugMode && !gl.getShaderParameter(shader, gl.COMPILE_STATUS))
|
||
throw gl.getShaderInfoLog(shader);
|
||
return shader;
|
||
}
|
||
_uniform1f(one, value) {
|
||
var uploadedValue = one.uploadedValue;
|
||
if (uploadedValue[0] !== value) {
|
||
Laya.LayaGL.instance.uniform1f(one.location, uploadedValue[0] = value);
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
_uniform1fv(one, value) {
|
||
if (value.length < 4) {
|
||
var uploadedValue = one.uploadedValue;
|
||
if (uploadedValue[0] !== value[0] || uploadedValue[1] !== value[1] || uploadedValue[2] !== value[2] || uploadedValue[3] !== value[3]) {
|
||
Laya.LayaGL.instance.uniform1fv(one.location, value);
|
||
uploadedValue[0] = value[0];
|
||
uploadedValue[1] = value[1];
|
||
uploadedValue[2] = value[2];
|
||
uploadedValue[3] = value[3];
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
else {
|
||
Laya.LayaGL.instance.uniform1fv(one.location, value);
|
||
return 1;
|
||
}
|
||
}
|
||
_uniform_vec2(one, v) {
|
||
var uploadedValue = one.uploadedValue;
|
||
if (uploadedValue[0] !== v.x || uploadedValue[1] !== v.y) {
|
||
Laya.LayaGL.instance.uniform2f(one.location, uploadedValue[0] = v.x, uploadedValue[1] = v.y);
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
_uniform_vec2v(one, value) {
|
||
if (value.length < 2) {
|
||
var uploadedValue = one.uploadedValue;
|
||
if (uploadedValue[0] !== value[0] || uploadedValue[1] !== value[1] || uploadedValue[2] !== value[2] || uploadedValue[3] !== value[3]) {
|
||
Laya.LayaGL.instance.uniform2fv(one.location, value);
|
||
uploadedValue[0] = value[0];
|
||
uploadedValue[1] = value[1];
|
||
uploadedValue[2] = value[2];
|
||
uploadedValue[3] = value[3];
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
else {
|
||
Laya.LayaGL.instance.uniform2fv(one.location, value);
|
||
return 1;
|
||
}
|
||
}
|
||
_uniform_vec3(one, v) {
|
||
var uploadedValue = one.uploadedValue;
|
||
if (uploadedValue[0] !== v.x || uploadedValue[1] !== v.y || uploadedValue[2] !== v.z) {
|
||
Laya.LayaGL.instance.uniform3f(one.location, uploadedValue[0] = v.x, uploadedValue[1] = v.y, uploadedValue[2] = v.z);
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
_uniform_vec3v(one, v) {
|
||
Laya.LayaGL.instance.uniform3fv(one.location, v);
|
||
return 1;
|
||
}
|
||
_uniform_vec4(one, v) {
|
||
var uploadedValue = one.uploadedValue;
|
||
if (uploadedValue[0] !== v.x || uploadedValue[1] !== v.y || uploadedValue[2] !== v.z || uploadedValue[3] !== v.w) {
|
||
Laya.LayaGL.instance.uniform4f(one.location, uploadedValue[0] = v.x, uploadedValue[1] = v.y, uploadedValue[2] = v.z, uploadedValue[3] = v.w);
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
_uniform_vec4v(one, v) {
|
||
Laya.LayaGL.instance.uniform4fv(one.location, v);
|
||
return 1;
|
||
}
|
||
_uniformMatrix2fv(one, value) {
|
||
Laya.LayaGL.instance.uniformMatrix2fv(one.location, false, value);
|
||
return 1;
|
||
}
|
||
_uniformMatrix3fv(one, value) {
|
||
Laya.LayaGL.instance.uniformMatrix3fv(one.location, false, value);
|
||
return 1;
|
||
}
|
||
_uniformMatrix4f(one, m) {
|
||
var value = m.elements;
|
||
Laya.LayaGL.instance.uniformMatrix4fv(one.location, false, value);
|
||
return 1;
|
||
}
|
||
_uniformMatrix4fv(one, m) {
|
||
Laya.LayaGL.instance.uniformMatrix4fv(one.location, false, m);
|
||
return 1;
|
||
}
|
||
_uniform1i(one, value) {
|
||
var uploadedValue = one.uploadedValue;
|
||
if (uploadedValue[0] !== value) {
|
||
Laya.LayaGL.instance.uniform1i(one.location, uploadedValue[0] = value);
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
_uniform1iv(one, value) {
|
||
Laya.LayaGL.instance.uniform1iv(one.location, value);
|
||
return 1;
|
||
}
|
||
_uniform_ivec2(one, value) {
|
||
var uploadedValue = one.uploadedValue;
|
||
if (uploadedValue[0] !== value[0] || uploadedValue[1] !== value[1]) {
|
||
Laya.LayaGL.instance.uniform2i(one.location, uploadedValue[0] = value[0], uploadedValue[1] = value[1]);
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
_uniform_ivec2v(one, value) {
|
||
Laya.LayaGL.instance.uniform2iv(one.location, value);
|
||
return 1;
|
||
}
|
||
_uniform_vec3i(one, value) {
|
||
var uploadedValue = one.uploadedValue;
|
||
if (uploadedValue[0] !== value[0] || uploadedValue[1] !== value[1] || uploadedValue[2] !== value[2]) {
|
||
Laya.LayaGL.instance.uniform3i(one.location, uploadedValue[0] = value[0], uploadedValue[1] = value[1], uploadedValue[2] = value[2]);
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
_uniform_vec3vi(one, value) {
|
||
Laya.LayaGL.instance.uniform3iv(one.location, value);
|
||
return 1;
|
||
}
|
||
_uniform_vec4i(one, value) {
|
||
var uploadedValue = one.uploadedValue;
|
||
if (uploadedValue[0] !== value[0] || uploadedValue[1] !== value[1] || uploadedValue[2] !== value[2] || uploadedValue[3] !== value[3]) {
|
||
Laya.LayaGL.instance.uniform4i(one.location, uploadedValue[0] = value[0], uploadedValue[1] = value[1], uploadedValue[2] = value[2], uploadedValue[3] = value[3]);
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
_uniform_vec4vi(one, value) {
|
||
Laya.LayaGL.instance.uniform4iv(one.location, value);
|
||
return 1;
|
||
}
|
||
_uniform_sampler2D(one, texture) {
|
||
var value = texture._getSource() || texture.defaulteTexture._getSource();
|
||
var gl = Laya.LayaGL.instance;
|
||
Laya.WebGLContext.activeTexture(gl, one.textureID);
|
||
Laya.WebGLContext.bindTexture(gl, gl.TEXTURE_2D, value);
|
||
return 0;
|
||
}
|
||
_uniform_sampler3D(one, texture) {
|
||
var value = texture._getSource() || texture.defaulteTexture._getSource();
|
||
var gl = Laya.LayaGL.instance;
|
||
Laya.WebGLContext.activeTexture(gl, one.textureID);
|
||
Laya.WebGLContext.bindTexture(gl, WebGL2RenderingContext.TEXTURE_3D, value);
|
||
return 0;
|
||
}
|
||
_uniform_samplerCube(one, texture) {
|
||
var value = texture._getSource() || texture.defaulteTexture._getSource();
|
||
var gl = Laya.LayaGL.instance;
|
||
Laya.WebGLContext.activeTexture(gl, one.textureID);
|
||
Laya.WebGLContext.bindTexture(gl, gl.TEXTURE_CUBE_MAP, value);
|
||
return 0;
|
||
}
|
||
bind() {
|
||
return Laya.WebGLContext.useProgram(Laya.LayaGL.instance, this._program);
|
||
}
|
||
uploadUniforms(shaderUniform, shaderDatas, uploadUnTexture) {
|
||
Laya.Stat.shaderCall += Laya.LayaGLRunner.uploadShaderUniforms(Laya.LayaGL.instance, shaderUniform, shaderDatas, uploadUnTexture);
|
||
}
|
||
uploadRenderStateBlendDepth(shaderDatas) {
|
||
var gl = Laya.LayaGL.instance;
|
||
var renderState = this._shaderPass.renderState;
|
||
var datas = shaderDatas.getData();
|
||
var depthWrite = this._getRenderState(datas, Shader3D.RENDER_STATE_DEPTH_WRITE);
|
||
var depthTest = this._getRenderState(datas, Shader3D.RENDER_STATE_DEPTH_TEST);
|
||
var blend = this._getRenderState(datas, Shader3D.RENDER_STATE_BLEND);
|
||
depthWrite == null && (depthWrite = renderState.depthWrite);
|
||
depthTest == null && (depthTest = renderState.depthTest);
|
||
blend == null && (blend = renderState.blend);
|
||
Laya.WebGLContext.setDepthMask(gl, depthWrite);
|
||
if (depthTest === RenderState.DEPTHTEST_OFF)
|
||
Laya.WebGLContext.setDepthTest(gl, false);
|
||
else {
|
||
Laya.WebGLContext.setDepthTest(gl, true);
|
||
Laya.WebGLContext.setDepthFunc(gl, depthTest);
|
||
}
|
||
switch (blend) {
|
||
case RenderState.BLEND_DISABLE:
|
||
Laya.WebGLContext.setBlend(gl, false);
|
||
break;
|
||
case RenderState.BLEND_ENABLE_ALL:
|
||
var blendEquation = this._getRenderState(datas, Shader3D.RENDER_STATE_BLEND_EQUATION);
|
||
var srcBlend = this._getRenderState(datas, Shader3D.RENDER_STATE_BLEND_SRC);
|
||
var dstBlend = this._getRenderState(datas, Shader3D.RENDER_STATE_BLEND_DST);
|
||
blendEquation == null && (blendEquation = renderState.blendEquation);
|
||
srcBlend == null && (srcBlend = renderState.srcBlend);
|
||
dstBlend == null && (dstBlend = renderState.dstBlend);
|
||
Laya.WebGLContext.setBlend(gl, true);
|
||
Laya.WebGLContext.setBlendEquation(gl, blendEquation);
|
||
Laya.WebGLContext.setBlendFunc(gl, srcBlend, dstBlend);
|
||
break;
|
||
case RenderState.BLEND_ENABLE_SEPERATE:
|
||
var blendEquationRGB = this._getRenderState(datas, Shader3D.RENDER_STATE_BLEND_EQUATION_RGB);
|
||
var blendEquationAlpha = this._getRenderState(datas, Shader3D.RENDER_STATE_BLEND_EQUATION_ALPHA);
|
||
var srcRGB = this._getRenderState(datas, Shader3D.RENDER_STATE_BLEND_SRC_RGB);
|
||
var dstRGB = this._getRenderState(datas, Shader3D.RENDER_STATE_BLEND_DST_RGB);
|
||
var srcAlpha = this._getRenderState(datas, Shader3D.RENDER_STATE_BLEND_SRC_ALPHA);
|
||
var dstAlpha = this._getRenderState(datas, Shader3D.RENDER_STATE_BLEND_DST_ALPHA);
|
||
blendEquationRGB == null && (blendEquationRGB = renderState.blendEquationRGB);
|
||
blendEquationAlpha == null && (blendEquationAlpha = renderState.blendEquationAlpha);
|
||
srcRGB == null && (srcRGB = renderState.srcBlendRGB);
|
||
dstRGB == null && (dstRGB = renderState.dstBlendRGB);
|
||
srcAlpha == null && (srcAlpha = renderState.srcBlendAlpha);
|
||
dstAlpha == null && (dstAlpha = renderState.dstBlendAlpha);
|
||
Laya.WebGLContext.setBlend(gl, true);
|
||
Laya.WebGLContext.setBlendEquationSeparate(gl, blendEquationRGB, blendEquationAlpha);
|
||
Laya.WebGLContext.setBlendFuncSeperate(gl, srcRGB, dstRGB, srcAlpha, dstAlpha);
|
||
break;
|
||
}
|
||
}
|
||
uploadRenderStateFrontFace(shaderDatas, isTarget, invertFront) {
|
||
var gl = Laya.LayaGL.instance;
|
||
var renderState = this._shaderPass.renderState;
|
||
var datas = shaderDatas.getData();
|
||
var cull = this._getRenderState(datas, Shader3D.RENDER_STATE_CULL);
|
||
cull == null && (cull = renderState.cull);
|
||
var forntFace;
|
||
switch (cull) {
|
||
case RenderState.CULL_NONE:
|
||
Laya.WebGLContext.setCullFace(gl, false);
|
||
break;
|
||
case RenderState.CULL_FRONT:
|
||
Laya.WebGLContext.setCullFace(gl, true);
|
||
if (isTarget) {
|
||
if (invertFront)
|
||
forntFace = gl.CCW;
|
||
else
|
||
forntFace = gl.CW;
|
||
}
|
||
else {
|
||
if (invertFront)
|
||
forntFace = gl.CW;
|
||
else
|
||
forntFace = gl.CCW;
|
||
}
|
||
Laya.WebGLContext.setFrontFace(gl, forntFace);
|
||
break;
|
||
case RenderState.CULL_BACK:
|
||
Laya.WebGLContext.setCullFace(gl, true);
|
||
if (isTarget) {
|
||
if (invertFront)
|
||
forntFace = gl.CW;
|
||
else
|
||
forntFace = gl.CCW;
|
||
}
|
||
else {
|
||
if (invertFront)
|
||
forntFace = gl.CCW;
|
||
else
|
||
forntFace = gl.CW;
|
||
}
|
||
Laya.WebGLContext.setFrontFace(gl, forntFace);
|
||
break;
|
||
}
|
||
}
|
||
uploadCustomUniform(index, data) {
|
||
Laya.Stat.shaderCall += Laya.LayaGLRunner.uploadCustomUniform(Laya.LayaGL.instance, this._customUniformParamsMap, index, data);
|
||
}
|
||
_uniformMatrix2fvForNative(one, value) {
|
||
Laya.LayaGL.instance.uniformMatrix2fvEx(one.location, false, value);
|
||
return 1;
|
||
}
|
||
_uniformMatrix3fvForNative(one, value) {
|
||
Laya.LayaGL.instance.uniformMatrix3fvEx(one.location, false, value);
|
||
return 1;
|
||
}
|
||
_uniformMatrix4fvForNative(one, m) {
|
||
Laya.LayaGL.instance.uniformMatrix4fvEx(one.location, false, m);
|
||
return 1;
|
||
}
|
||
}
|
||
|
||
class SingletonList {
|
||
constructor() {
|
||
this.elements = [];
|
||
this.length = 0;
|
||
}
|
||
_add(element) {
|
||
if (this.length === this.elements.length)
|
||
this.elements.push(element);
|
||
else
|
||
this.elements[this.length] = element;
|
||
}
|
||
add(element) {
|
||
if (this.length === this.elements.length)
|
||
this.elements.push(element);
|
||
else
|
||
this.elements[this.length] = element;
|
||
this.length++;
|
||
}
|
||
}
|
||
|
||
class SimpleSingletonList extends SingletonList {
|
||
constructor() {
|
||
super();
|
||
}
|
||
add(element) {
|
||
var index = element._getIndexInList();
|
||
if (index !== -1)
|
||
throw "SimpleSingletonList:" + element + " has in SingletonList.";
|
||
this._add(element);
|
||
element._setIndexInList(this.length++);
|
||
}
|
||
remove(element) {
|
||
var index = element._getIndexInList();
|
||
this.length--;
|
||
if (index !== this.length) {
|
||
var end = this.elements[this.length];
|
||
this.elements[index] = end;
|
||
end._setIndexInList(index);
|
||
}
|
||
element._setIndexInList(-1);
|
||
}
|
||
clear() {
|
||
var elements = this.elements;
|
||
for (var i = 0, n = this.length; i < n; i++)
|
||
elements[i]._setIndexInList(-1);
|
||
this.length = 0;
|
||
}
|
||
clearElement() {
|
||
this.elements = null;
|
||
this.length = 0;
|
||
}
|
||
}
|
||
|
||
class Color {
|
||
constructor(r = 1, g = 1, b = 1, a = 1) {
|
||
this.r = r;
|
||
this.g = g;
|
||
this.b = b;
|
||
this.a = a;
|
||
}
|
||
static gammaToLinearSpace(value) {
|
||
if (value <= 0.04045)
|
||
return value / 12.92;
|
||
else if (value < 1.0)
|
||
return Math.pow((value + 0.055) / 1.055, 2.4);
|
||
else
|
||
return Math.pow(value, 2.4);
|
||
}
|
||
static linearToGammaSpace(value) {
|
||
if (value <= 0.0)
|
||
return 0.0;
|
||
else if (value <= 0.0031308)
|
||
return 12.92 * value;
|
||
else if (value <= 1.0)
|
||
return 1.055 * Math.pow(value, 0.41666) - 0.055;
|
||
else
|
||
return Math.pow(value, 0.41666);
|
||
}
|
||
toLinear(out) {
|
||
out.r = Color.gammaToLinearSpace(this.r);
|
||
out.g = Color.gammaToLinearSpace(this.g);
|
||
out.b = Color.gammaToLinearSpace(this.b);
|
||
}
|
||
toGamma(out) {
|
||
out.r = Color.linearToGammaSpace(this.r);
|
||
out.g = Color.linearToGammaSpace(this.g);
|
||
out.b = Color.linearToGammaSpace(this.b);
|
||
}
|
||
cloneTo(destObject) {
|
||
var destColor = destObject;
|
||
destColor.r = this.r;
|
||
destColor.g = this.g;
|
||
destColor.b = this.b;
|
||
destColor.a = this.a;
|
||
}
|
||
clone() {
|
||
var dest = new Color();
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
forNativeElement() {
|
||
}
|
||
}
|
||
Color.RED = new Color(1, 0, 0, 1);
|
||
Color.GREEN = new Color(0, 1, 0, 1);
|
||
Color.BLUE = new Color(0, 0, 1, 1);
|
||
Color.CYAN = new Color(0, 1, 1, 1);
|
||
Color.YELLOW = new Color(1, 0.92, 0.016, 1);
|
||
Color.MAGENTA = new Color(1, 0, 1, 1);
|
||
Color.GRAY = new Color(0.5, 0.5, 0.5, 1);
|
||
Color.WHITE = new Color(1, 1, 1, 1);
|
||
Color.BLACK = new Color(0, 0, 0, 1);
|
||
|
||
class CameraCullInfo {
|
||
}
|
||
class ShadowCullInfo {
|
||
}
|
||
class FrustumCulling {
|
||
static __init__() {
|
||
}
|
||
static _drawTraversalCullingBound(renderList, debugTool) {
|
||
var renders = renderList.elements;
|
||
for (var i = 0, n = renderList.length; i < n; i++) {
|
||
var color = FrustumCulling._tempColor0;
|
||
color.r = 0;
|
||
color.g = 1;
|
||
color.b = 0;
|
||
color.a = 1;
|
||
Utils3D._drawBound(debugTool, renders[i].bounds._getBoundBox(), color);
|
||
}
|
||
}
|
||
static _traversalCulling(cameraCullInfo, scene, context, renderList, customShader, replacementTag, isShadowCasterCull) {
|
||
var renders = renderList.elements;
|
||
var boundFrustum = cameraCullInfo.boundFrustum;
|
||
var camPos = cameraCullInfo.position;
|
||
var cullMask = cameraCullInfo.cullingMask;
|
||
var loopCount = Laya.Stat.loopCount;
|
||
for (var i = 0, n = renderList.length; i < n; i++) {
|
||
var render = renders[i];
|
||
var canPass;
|
||
if (isShadowCasterCull)
|
||
canPass = render._castShadow && render._enable;
|
||
else
|
||
canPass = ((Math.pow(2, render._owner._layer) & cullMask) != 0) && render._enable;
|
||
if (canPass) {
|
||
Laya.Stat.frustumCulling++;
|
||
if (!cameraCullInfo.useOcclusionCulling || render._needRender(boundFrustum, context)) {
|
||
render._renderMark = loopCount;
|
||
render._distanceForSort = Vector3.distance(render.bounds.getCenter(), camPos);
|
||
var elements = render._renderElements;
|
||
for (var j = 0, m = elements.length; j < m; j++)
|
||
elements[j]._update(scene, context, customShader, replacementTag);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
static renderObjectCulling(cameraCullInfo, scene, context, customShader, replacementTag, isShadowCasterCull) {
|
||
var opaqueQueue = scene._opaqueQueue;
|
||
var transparentQueue = scene._transparentQueue;
|
||
var renderList = scene._renders;
|
||
scene._clearRenderQueue();
|
||
var octree = scene._octree;
|
||
if (octree) {
|
||
octree.updateMotionObjects();
|
||
octree.shrinkRootIfPossible();
|
||
octree.getCollidingWithFrustum(cameraCullInfo, context, customShader, replacementTag, isShadowCasterCull);
|
||
}
|
||
FrustumCulling._traversalCulling(cameraCullInfo, scene, context, renderList, customShader, replacementTag, isShadowCasterCull);
|
||
if (FrustumCulling.debugFrustumCulling) {
|
||
var debugTool = scene._debugTool;
|
||
debugTool.clear();
|
||
if (octree) {
|
||
octree.drawAllBounds(debugTool);
|
||
octree.drawAllObjects(debugTool);
|
||
}
|
||
FrustumCulling._drawTraversalCullingBound(renderList, debugTool);
|
||
}
|
||
var count = opaqueQueue.elements.length;
|
||
(count > 0) && (opaqueQueue._quickSort(0, count - 1));
|
||
count = transparentQueue.elements.length;
|
||
(count > 0) && (transparentQueue._quickSort(0, count - 1));
|
||
}
|
||
static cullingShadow(cullInfo, scene, context) {
|
||
scene._clearRenderQueue();
|
||
var opaqueQueue = scene._opaqueQueue;
|
||
if (!scene._octree) {
|
||
var renderList = scene._renders;
|
||
var position = cullInfo.position;
|
||
var renders = renderList.elements;
|
||
var loopCount = Laya.Stat.loopCount;
|
||
for (var i = 0, n = renderList.length; i < n; i++) {
|
||
var render = renders[i];
|
||
var canPass = render._castShadow && render._enable;
|
||
if (canPass) {
|
||
Laya.Stat.frustumCulling++;
|
||
let pass = FrustumCulling.cullingRenderBounds(render.bounds, cullInfo);
|
||
if (pass) {
|
||
render._renderMark = loopCount;
|
||
render._distanceForSort = Vector3.distance(render.bounds.getCenter(), position);
|
||
var elements = render._renderElements;
|
||
for (var j = 0, m = elements.length; j < m; j++)
|
||
elements[j]._update(scene, context, null, null);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
let octree = scene._octree;
|
||
octree.updateMotionObjects();
|
||
octree.shrinkRootIfPossible();
|
||
octree._rootNode.getCollidingWithCastShadowFrustum(cullInfo, context);
|
||
}
|
||
return opaqueQueue.elements.length > 0 ? true : false;
|
||
}
|
||
static cullingRenderBounds(bounds, cullInfo) {
|
||
var cullPlaneCount = cullInfo.cullPlaneCount;
|
||
var cullPlanes = cullInfo.cullPlanes;
|
||
var min = bounds.getMin();
|
||
var max = bounds.getMax();
|
||
var minX = min.x;
|
||
var minY = min.y;
|
||
var minZ = min.z;
|
||
var maxX = max.x;
|
||
var maxY = max.y;
|
||
var maxZ = max.z;
|
||
var pass = true;
|
||
for (var j = 0; j < cullPlaneCount; j++) {
|
||
var plane = cullPlanes[j];
|
||
var normal = plane.normal;
|
||
if (plane.distance + (normal.x * (normal.x < 0.0 ? minX : maxX)) + (normal.y * (normal.y < 0.0 ? minY : maxY)) + (normal.z * (normal.z < 0.0 ? minZ : maxZ)) < 0.0) {
|
||
pass = false;
|
||
break;
|
||
}
|
||
}
|
||
return pass;
|
||
}
|
||
static cullingSpotShadow(cameraCullInfo, scene, context) {
|
||
var opaqueQueue = scene._opaqueQueue;
|
||
scene._clearRenderQueue();
|
||
if (!scene._octree) {
|
||
var renderList = scene._renders;
|
||
var renders = renderList.elements;
|
||
var loopCount = Laya.Stat.loopCount;
|
||
for (var i = 0, n = renderList.length; i < n; i++) {
|
||
var render = renders[i];
|
||
var canPass = render._castShadow && render._enable;
|
||
if (canPass) {
|
||
if (render._needRender(cameraCullInfo.boundFrustum, context)) {
|
||
var bounds = render.bounds;
|
||
render._renderMark = loopCount;
|
||
render._distanceForSort = Vector3.distance(bounds.getCenter(), cameraCullInfo.position);
|
||
var elements = render._renderElements;
|
||
for (var j = 0, m = elements.length; j < m; j++)
|
||
elements[j]._update(scene, context, null, null);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
let octree = scene._octree;
|
||
octree.updateMotionObjects();
|
||
octree.shrinkRootIfPossible();
|
||
octree.getCollidingWithFrustum(cameraCullInfo, context, null, null, true);
|
||
}
|
||
return opaqueQueue.elements.length > 0 ? true : false;
|
||
}
|
||
static renderObjectCullingNative(camera, scene, context, renderList, customShader, replacementTag) {
|
||
var i, j, m;
|
||
var opaqueQueue = scene._opaqueQueue;
|
||
var transparentQueue = scene._transparentQueue;
|
||
scene._clearRenderQueue();
|
||
var validCount = renderList.length;
|
||
var renders = renderList.elements;
|
||
for (i = 0; i < validCount; i++) {
|
||
renders[i].bounds;
|
||
renders[i]._updateForNative && renders[i]._updateForNative(context);
|
||
}
|
||
FrustumCulling.cullingNative(camera._boundFrustumBuffer, FrustumCulling._cullingBuffer, scene._cullingBufferIndices, validCount, scene._cullingBufferResult);
|
||
var loopCount = Laya.Stat.loopCount;
|
||
var camPos = context.camera._transform.position;
|
||
for (i = 0; i < validCount; i++) {
|
||
var render = renders[i];
|
||
if (!camera.useOcclusionCulling || (camera._isLayerVisible(render._owner._layer) && render._enable && scene._cullingBufferResult[i])) {
|
||
render._renderMark = loopCount;
|
||
render._distanceForSort = Vector3.distance(render.bounds.getCenter(), camPos);
|
||
var elements = render._renderElements;
|
||
for (j = 0, m = elements.length; j < m; j++) {
|
||
var element = elements[j];
|
||
element._update(scene, context, customShader, replacementTag);
|
||
}
|
||
}
|
||
}
|
||
var count = opaqueQueue.elements.length;
|
||
(count > 0) && (opaqueQueue._quickSort(0, count - 1));
|
||
count = transparentQueue.elements.length;
|
||
(count > 0) && (transparentQueue._quickSort(0, count - 1));
|
||
}
|
||
static cullingNative(boundFrustumBuffer, cullingBuffer, cullingBufferIndices, cullingCount, cullingBufferResult) {
|
||
return Laya.LayaGL.instance.culling(boundFrustumBuffer, cullingBuffer, cullingBufferIndices, cullingCount, cullingBufferResult);
|
||
}
|
||
}
|
||
FrustumCulling._tempColor0 = new Color();
|
||
FrustumCulling._cameraCullInfo = new CameraCullInfo();
|
||
FrustumCulling._shadowCullInfo = new ShadowCullInfo();
|
||
FrustumCulling.debugFrustumCulling = false;
|
||
|
||
class LightBound {
|
||
}
|
||
class ClusterData {
|
||
constructor() {
|
||
this.updateMark = -1;
|
||
this.pointLightCount = 0;
|
||
this.spotLightCount = 0;
|
||
this.indices = [];
|
||
}
|
||
}
|
||
class Cluster {
|
||
constructor(xSlices, ySlices, zSlices, maxLightsPerClusterAverage) {
|
||
this._updateMark = 0;
|
||
this._depthSliceParam = new Vector2();
|
||
this._xSlices = xSlices;
|
||
this._ySlices = ySlices;
|
||
this._zSlices = zSlices;
|
||
var clusterTexWidth = xSlices * ySlices;
|
||
var clisterTexHeight = zSlices * (1 + Math.ceil(maxLightsPerClusterAverage / 4));
|
||
this._clusterTexture = Utils3D._createFloatTextureBuffer(clusterTexWidth, clisterTexHeight);
|
||
this._clusterTexture.lock = true;
|
||
this._clusterPixels = new Float32Array(clusterTexWidth * clisterTexHeight * 4);
|
||
var clusterDatas = new Array(this._zSlices);
|
||
for (var z = 0; z < this._zSlices; z++) {
|
||
clusterDatas[z] = new Array(this._ySlices);
|
||
for (var y = 0; y < this._ySlices; y++) {
|
||
clusterDatas[z][y] = new Array(this._xSlices);
|
||
for (var x = 0; x < this._xSlices; x++)
|
||
clusterDatas[z][y][x] = new ClusterData();
|
||
}
|
||
}
|
||
this._clusterDatas = clusterDatas;
|
||
}
|
||
_placePointLightToClusters(lightIndex, lightBound) {
|
||
var clusterDatas = this._clusterDatas;
|
||
var updateMark = this._updateMark;
|
||
for (var z = lightBound.zMin, zEnd = lightBound.zMax; z < zEnd; z++) {
|
||
for (var y = lightBound.yMin, yEnd = lightBound.yMax; y < yEnd; y++) {
|
||
for (var x = lightBound.xMin, xEnd = lightBound.xMax; x < xEnd; x++) {
|
||
var data = clusterDatas[z][y][x];
|
||
if (data.updateMark != updateMark) {
|
||
data.pointLightCount = 0;
|
||
data.spotLightCount = 0;
|
||
data.updateMark = updateMark;
|
||
}
|
||
var indices = data.indices;
|
||
var lightCount = data.pointLightCount++;
|
||
if (lightCount < indices.length)
|
||
indices[lightCount] = lightIndex;
|
||
else
|
||
indices.push(lightIndex);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
_placeSpotLightToClusters(lightIndex, lightBound) {
|
||
var clusterDatas = this._clusterDatas;
|
||
var updateMark = this._updateMark;
|
||
for (var z = lightBound.zMin, zEnd = lightBound.zMax; z < zEnd; z++) {
|
||
for (var y = lightBound.yMin, yEnd = lightBound.yMax; y < yEnd; y++) {
|
||
for (var x = lightBound.xMin, xEnd = lightBound.xMax; x < xEnd; x++) {
|
||
var data = clusterDatas[z][y][x];
|
||
if (data.updateMark != updateMark) {
|
||
data.pointLightCount = 0;
|
||
data.spotLightCount = 0;
|
||
data.updateMark = updateMark;
|
||
}
|
||
var indices = data.indices;
|
||
var lightCount = data.pointLightCount + data.spotLightCount++;
|
||
if (lightCount < indices.length)
|
||
indices[lightCount] = lightIndex;
|
||
else
|
||
indices.push(lightIndex);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
_insertConePlane(origin, forward, radius, halfAngle, pNor) {
|
||
var V1 = Cluster._tempVector36;
|
||
var V2 = Cluster._tempVector37;
|
||
Vector3.cross(pNor, forward, V1);
|
||
Vector3.cross(V1, forward, V2);
|
||
Vector3.normalize(V2, V2);
|
||
var tanR = radius * Math.tan(halfAngle);
|
||
var capRimX = origin.x + radius * forward.x + tanR * V2.x;
|
||
var capRimY = origin.y + radius * forward.y + tanR * V2.y;
|
||
var capRimZ = origin.z + radius * forward.z + tanR * V2.z;
|
||
return capRimX * pNor.x + capRimY * pNor.y + capRimZ * pNor.z <= 0 || origin.x * pNor.x + origin.y * pNor.y + origin.z * pNor.z <= 0;
|
||
}
|
||
_shrinkSphereLightZPerspective(near, far, lightviewPos, radius, lightBound) {
|
||
var lvZ = lightviewPos.z;
|
||
var minZ = lvZ - radius;
|
||
var maxZ = lvZ + radius;
|
||
if ((minZ > far) || (maxZ <= near))
|
||
return false;
|
||
var depthSliceParam = this._depthSliceParam;
|
||
lightBound.zMin = Math.floor(Math.log2(Math.max(minZ, near)) * depthSliceParam.x - depthSliceParam.y);
|
||
lightBound.zMax = Math.min(Math.ceil(Math.log2(maxZ) * depthSliceParam.x - depthSliceParam.y), this._zSlices);
|
||
return true;
|
||
}
|
||
_shrinkSpotLightZPerspective(near, far, viewLightPos, viewConeCap, radius, halfAngle, lightBound) {
|
||
var pbX = viewConeCap.x, pbY = viewConeCap.y, pbZ = viewConeCap.z;
|
||
var rb = Math.tan(halfAngle) * radius;
|
||
var paX = viewLightPos.x, paY = viewLightPos.y, paZ = viewLightPos.z;
|
||
var aX = pbX - paX, aY = pbY - paY, aZ = pbZ - paZ;
|
||
var dotA = aX * aX + aY * aY + aZ * aZ;
|
||
var eZ = Math.sqrt(1.0 - aZ * aZ / dotA);
|
||
var minZ = Math.max(Math.min(paZ, pbZ - eZ * rb), viewLightPos.z - radius);
|
||
var maxZ = Math.min(Math.max(paZ, pbZ + eZ * rb), viewLightPos.z + radius);
|
||
if ((minZ > far) || (maxZ <= near))
|
||
return false;
|
||
var depthSliceParam = this._depthSliceParam;
|
||
lightBound.zMin = Math.floor(Math.log2(Math.max(minZ, near)) * depthSliceParam.x - depthSliceParam.y);
|
||
lightBound.zMax = Math.min(Math.ceil(Math.log2(maxZ) * depthSliceParam.x - depthSliceParam.y), this._zSlices);
|
||
return true;
|
||
}
|
||
_shrinkSphereLightByBoundOrth(halfX, halfY, near, far, lightviewPos, radius, lightBound) {
|
||
var lvZ = lightviewPos.z;
|
||
var minZ = lvZ - radius, maxZ = lvZ + radius;
|
||
if ((minZ > far) || (maxZ <= near))
|
||
return false;
|
||
var lvX = lightviewPos.x;
|
||
var minX = lvX - radius, maxX = lvX + radius;
|
||
if ((minX > halfX) || (maxX <= -halfX))
|
||
return false;
|
||
var lvY = lightviewPos.y;
|
||
var minY = lvY - radius, maxY = lvY + radius;
|
||
if ((minY > halfY) || (maxY <= -halfY))
|
||
return false;
|
||
var xSlices = this._xSlices, ySlices = this._ySlices;
|
||
var depthSliceParam = this._depthSliceParam;
|
||
var xStride = halfX * 2 / xSlices, yStride = halfY * 2 / ySlices;
|
||
lightBound.xMin = Math.max(Math.floor((minX + halfX) / xStride), 0);
|
||
lightBound.xMax = Math.min(Math.ceil((maxX + halfX) / xStride), xSlices);
|
||
lightBound.yMin = Math.max(Math.floor((halfY - maxY) / yStride), 0);
|
||
lightBound.yMax = Math.min(Math.ceil((halfY - minY) / yStride), ySlices);
|
||
lightBound.zMin = Math.floor(Math.log2(Math.max(minZ, near)) * depthSliceParam.x - depthSliceParam.y);
|
||
lightBound.zMax = Math.min(Math.ceil(Math.log2(maxZ) * depthSliceParam.x - depthSliceParam.y), this._zSlices);
|
||
return true;
|
||
}
|
||
_shrinkSpotLightByBoundOrth(halfX, halfY, near, far, viewLightPos, viewConeCap, radius, halfAngle, lightBound) {
|
||
var pbX = viewConeCap.x, pbY = viewConeCap.y, pbZ = viewConeCap.z;
|
||
var rb = Math.tan(halfAngle) * radius;
|
||
var paX = viewLightPos.x, paY = viewLightPos.y, paZ = viewLightPos.z;
|
||
var aX = pbX - paX, aY = pbY - paY, aZ = pbZ - paZ;
|
||
var dotA = aX * aX + aY * aY + aZ * aZ;
|
||
var eZ = Math.sqrt(1.0 - aZ * aZ / dotA);
|
||
var minZ = Math.max(Math.min(paZ, pbZ - eZ * rb), viewLightPos.z - radius);
|
||
var maxZ = Math.min(Math.max(paZ, pbZ + eZ * rb), viewLightPos.z + radius);
|
||
if ((minZ > far) || (maxZ <= near))
|
||
return false;
|
||
var eX = Math.sqrt(1.0 - aX * aX / dotA);
|
||
var minX = Math.max(Math.min(paX, pbX - eX * rb), viewLightPos.x - radius);
|
||
var maxX = Math.min(Math.max(paX, pbX + eX * rb), viewLightPos.x + radius);
|
||
if ((minX > halfX) || (maxX <= -halfX))
|
||
return false;
|
||
var eY = Math.sqrt(1.0 - aY * aY / dotA);
|
||
var minY = Math.max(Math.min(paY, pbY - eY * rb), viewLightPos.y - radius);
|
||
var maxY = Math.min(Math.max(paY, pbY + eY * rb), viewLightPos.y + radius);
|
||
if ((minY > halfY) || (maxY <= -halfY))
|
||
return false;
|
||
var xSlices = this._xSlices, ySlices = this._ySlices;
|
||
var depthSliceParam = this._depthSliceParam;
|
||
var xStride = halfX * 2 / xSlices, yStride = halfY * 2 / ySlices;
|
||
lightBound.xMin = Math.max(Math.floor((minX + halfX) / xStride), 0);
|
||
lightBound.xMax = Math.min(Math.ceil((maxX + halfX) / xStride), xSlices);
|
||
lightBound.yMin = Math.max(Math.floor((halfY - maxY) / yStride), 0);
|
||
lightBound.yMax = Math.min(Math.ceil((halfY - minY) / yStride), ySlices);
|
||
lightBound.zMin = Math.floor(Math.log2(Math.max(minZ, near)) * depthSliceParam.x - depthSliceParam.y);
|
||
lightBound.zMax = Math.min(Math.ceil(Math.log2(maxZ) * depthSliceParam.x - depthSliceParam.y), this._zSlices);
|
||
return true;
|
||
}
|
||
_shrinkXYByRadiusPerspective(lightviewPos, radius, lightBound, xPlanes, yPlanes) {
|
||
var xMin, yMin;
|
||
var xMax, yMax;
|
||
var lvX = lightviewPos.x, lvY = lightviewPos.y, lvZ = lightviewPos.z;
|
||
var i;
|
||
var n = this._ySlices + 1;
|
||
for (i = 0; i < n; i++) {
|
||
var plane = yPlanes[i];
|
||
if (lvY * plane.y + lvZ * plane.z < radius) {
|
||
yMin = Math.max(0, i - 1);
|
||
break;
|
||
}
|
||
}
|
||
if (i == n)
|
||
return false;
|
||
yMax = this._ySlices;
|
||
for (i = yMin + 1; i < n; i++) {
|
||
var plane = yPlanes[i];
|
||
if (lvY * plane.y + lvZ * plane.z <= -radius) {
|
||
yMax = Math.max(0, i);
|
||
break;
|
||
}
|
||
}
|
||
n = this._xSlices + 1;
|
||
for (i = 0; i < n; i++) {
|
||
var plane = xPlanes[i];
|
||
if (lvX * plane.x + lvZ * plane.z < radius) {
|
||
xMin = Math.max(0, i - 1);
|
||
break;
|
||
}
|
||
}
|
||
xMax = this._xSlices;
|
||
for (i = xMin + 1; i < n; i++) {
|
||
var plane = xPlanes[i];
|
||
if (lvX * plane.x + lvZ * plane.z <= -radius) {
|
||
xMax = Math.max(0, i);
|
||
break;
|
||
}
|
||
}
|
||
lightBound.xMin = xMin;
|
||
lightBound.xMax = xMax;
|
||
lightBound.yMin = yMin;
|
||
lightBound.yMax = yMax;
|
||
return true;
|
||
}
|
||
_shrinkSpotXYByConePerspective(lightviewPos, viewForward, radius, halfAngle, lightBound, xPlanes, yPlanes) {
|
||
var xMin, yMin;
|
||
var xMax, yMax;
|
||
var normal = Cluster._tempVector32;
|
||
var n = lightBound.yMax + 1;
|
||
for (var i = lightBound.yMin + 1; i < n; i++) {
|
||
if (this._insertConePlane(lightviewPos, viewForward, radius, halfAngle, yPlanes[i])) {
|
||
yMin = Math.max(0, i - 1);
|
||
break;
|
||
}
|
||
}
|
||
yMax = lightBound.yMax;
|
||
for (var i = yMin + 1; i < n; i++) {
|
||
var plane = yPlanes[i];
|
||
normal.setValue(0, -plane.y, -plane.z);
|
||
if (!this._insertConePlane(lightviewPos, viewForward, radius, halfAngle, normal)) {
|
||
yMax = Math.max(0, i);
|
||
break;
|
||
}
|
||
}
|
||
n = lightBound.xMax + 1;
|
||
for (var i = lightBound.xMin + 1; i < n; i++) {
|
||
if (this._insertConePlane(lightviewPos, viewForward, radius, halfAngle, xPlanes[i])) {
|
||
xMin = Math.max(0, i - 1);
|
||
break;
|
||
}
|
||
}
|
||
xMax = lightBound.xMax;
|
||
for (var i = xMin + 1; i < n; i++) {
|
||
var plane = xPlanes[i];
|
||
normal.setValue(-plane.x, 0, -plane.z);
|
||
if (!this._insertConePlane(lightviewPos, viewForward, radius, halfAngle, normal)) {
|
||
xMax = Math.max(0, i);
|
||
break;
|
||
}
|
||
}
|
||
lightBound.xMin = xMin;
|
||
lightBound.xMax = xMax;
|
||
lightBound.yMin = yMin;
|
||
lightBound.yMax = yMax;
|
||
}
|
||
_updatePointLightPerspective(near, far, viewMat, pointLight, lightIndex, xPlanes, yPlanes) {
|
||
var lightBound = Cluster._tempLightBound;
|
||
var lightviewPos = Cluster._tempVector30;
|
||
Vector3.transformV3ToV3(pointLight._transform.position, viewMat, lightviewPos);
|
||
lightviewPos.z *= -1;
|
||
if (!this._shrinkSphereLightZPerspective(near, far, lightviewPos, pointLight.range, lightBound))
|
||
return;
|
||
if (!this._shrinkXYByRadiusPerspective(lightviewPos, pointLight.range, lightBound, xPlanes, yPlanes))
|
||
return;
|
||
this._placePointLightToClusters(lightIndex, lightBound);
|
||
}
|
||
_updateSpotLightPerspective(near, far, viewMat, spotLight, lightIndex, xPlanes, yPlanes) {
|
||
var lightBound = Cluster._tempLightBound;
|
||
var viewPos = Cluster._tempVector30;
|
||
var forward = Cluster._tempVector31;
|
||
var viewConeCap = Cluster._tempVector34;
|
||
var position = spotLight._transform.position;
|
||
var range = spotLight.range;
|
||
spotLight._transform.worldMatrix.getForward(forward);
|
||
Vector3.normalize(forward, forward);
|
||
Vector3.scale(forward, range, viewConeCap);
|
||
Vector3.add(position, viewConeCap, viewConeCap);
|
||
Vector3.transformV3ToV3(position, viewMat, viewPos);
|
||
Vector3.transformV3ToV3(viewConeCap, viewMat, viewConeCap);
|
||
viewPos.z *= -1;
|
||
viewConeCap.z *= -1;
|
||
var halfAngle = (spotLight.spotAngle / 2) * Math.PI / 180;
|
||
if (!this._shrinkSpotLightZPerspective(near, far, viewPos, viewConeCap, range, halfAngle, lightBound))
|
||
return;
|
||
if (!this._shrinkXYByRadiusPerspective(viewPos, range, lightBound, xPlanes, yPlanes))
|
||
return;
|
||
var viewFor = Cluster._tempVector33;
|
||
viewFor.x = viewConeCap.x - viewPos.x, viewFor.y = viewConeCap.y - viewPos.y, viewFor.z = viewConeCap.z - viewPos.z;
|
||
Vector3.normalize(viewFor, viewFor);
|
||
this._shrinkSpotXYByConePerspective(viewPos, viewFor, range, halfAngle, lightBound, xPlanes, yPlanes);
|
||
this._placeSpotLightToClusters(lightIndex, lightBound);
|
||
}
|
||
_updatePointLightOrth(halfX, halfY, near, far, viewMat, pointLight, lightIndex) {
|
||
var lightBound = Cluster._tempLightBound;
|
||
var lightviewPos = Cluster._tempVector30;
|
||
Vector3.transformV3ToV3(pointLight._transform.position, viewMat, lightviewPos);
|
||
lightviewPos.z *= -1;
|
||
if (!this._shrinkSphereLightByBoundOrth(halfX, halfY, near, far, lightviewPos, pointLight.range, lightBound))
|
||
return;
|
||
this._placePointLightToClusters(lightIndex, lightBound);
|
||
}
|
||
_updateSpotLightOrth(halfX, halfY, near, far, viewMat, spotLight, lightIndex) {
|
||
var lightBound = Cluster._tempLightBound;
|
||
var viewPos = Cluster._tempVector30;
|
||
var forward = Cluster._tempVector31;
|
||
var viewConeCap = Cluster._tempVector34;
|
||
var position = spotLight._transform.position;
|
||
var range = spotLight.range;
|
||
spotLight._transform.worldMatrix.getForward(forward);
|
||
Vector3.normalize(forward, forward);
|
||
Vector3.scale(forward, range, viewConeCap);
|
||
Vector3.add(position, viewConeCap, viewConeCap);
|
||
Vector3.transformV3ToV3(position, viewMat, viewPos);
|
||
Vector3.transformV3ToV3(viewConeCap, viewMat, viewConeCap);
|
||
viewPos.z *= -1;
|
||
viewConeCap.z *= -1;
|
||
var halfAngle = (spotLight.spotAngle / 2) * Math.PI / 180;
|
||
if (!this._shrinkSpotLightByBoundOrth(halfX, halfY, near, far, viewPos, viewConeCap, range, halfAngle, lightBound))
|
||
return;
|
||
this._placeSpotLightToClusters(lightIndex, lightBound);
|
||
}
|
||
update(camera, scene) {
|
||
this._updateMark++;
|
||
var camNear = camera.nearPlane;
|
||
this._depthSliceParam.x = Config3D._config.lightClusterCount.z / Math.log2(camera.farPlane / camNear);
|
||
this._depthSliceParam.y = Math.log2(camNear) * this._depthSliceParam.x;
|
||
var near = camera.nearPlane;
|
||
var far = camera.farPlane;
|
||
var viewMat = camera.viewMatrix;
|
||
var curCount = scene._directionLights._length;
|
||
var pointLights = scene._pointLights;
|
||
var poiCount = pointLights._length;
|
||
var poiElements = pointLights._elements;
|
||
var spotLights = scene._spotLights;
|
||
var spoCount = spotLights._length;
|
||
var spoElements = spotLights._elements;
|
||
if (camera.orthographic) {
|
||
var halfY = camera.orthographicVerticalSize / 2.0;
|
||
var halfX = halfY * camera.aspectRatio;
|
||
for (var i = 0; i < poiCount; i++, curCount++)
|
||
this._updatePointLightOrth(halfX, halfY, near, far, viewMat, poiElements[i], curCount);
|
||
for (var i = 0; i < spoCount; i++, curCount++)
|
||
this._updateSpotLightOrth(halfX, halfY, near, far, viewMat, spoElements[i], curCount);
|
||
}
|
||
else {
|
||
camera._updateClusterPlaneXY();
|
||
var xPlanes = camera._clusterXPlanes;
|
||
var yPlanes = camera._clusterYPlanes;
|
||
for (var i = 0; i < poiCount; i++, curCount++)
|
||
this._updatePointLightPerspective(near, far, viewMat, poiElements[i], curCount, xPlanes, yPlanes);
|
||
for (var i = 0; i < spoCount; i++, curCount++)
|
||
this._updateSpotLightPerspective(near, far, viewMat, spoElements[i], curCount, xPlanes, yPlanes);
|
||
}
|
||
if (poiCount + spoCount > 0) {
|
||
var xSlices = this._xSlices, ySlices = this._ySlices, zSlices = this._zSlices;
|
||
var widthFloat = xSlices * ySlices * 4;
|
||
var lightOff = widthFloat * zSlices;
|
||
var clusterPixels = this._clusterPixels;
|
||
var clusterPixelsCount = clusterPixels.length;
|
||
var clusterDatas = this._clusterDatas;
|
||
var updateMark = this._updateMark;
|
||
var freeSpace = true;
|
||
for (var z = 0; z < zSlices; z++) {
|
||
for (var y = 0; y < ySlices; y++) {
|
||
for (var x = 0; x < xSlices; x++) {
|
||
var data = clusterDatas[z][y][x];
|
||
var clusterOff = (x + y * xSlices + z * xSlices * ySlices) * 4;
|
||
if (data.updateMark !== updateMark) {
|
||
clusterPixels[clusterOff] = 0;
|
||
clusterPixels[clusterOff + 1] = 0;
|
||
}
|
||
else {
|
||
if (freeSpace) {
|
||
var indices = data.indices;
|
||
var pCount = data.pointLightCount;
|
||
var sCount = data.spotLightCount;
|
||
var count = pCount + sCount;
|
||
if (lightOff + count < clusterPixelsCount) {
|
||
clusterPixels[clusterOff] = pCount;
|
||
clusterPixels[clusterOff + 1] = sCount;
|
||
clusterPixels[clusterOff + 2] = Math.floor(lightOff / widthFloat);
|
||
clusterPixels[clusterOff + 3] = lightOff % widthFloat;
|
||
for (var i = 0; i < count; i++)
|
||
clusterPixels[lightOff++] = indices[i];
|
||
}
|
||
else {
|
||
count = clusterPixelsCount - (lightOff + count);
|
||
pCount = Math.min(pCount, count);
|
||
clusterPixels[clusterOff] = pCount;
|
||
clusterPixels[clusterOff + 1] = Math.min(sCount, count - pCount);
|
||
clusterPixels[clusterOff + 2] = Math.floor(lightOff / widthFloat);
|
||
clusterPixels[clusterOff + 3] = lightOff % widthFloat;
|
||
for (var i = 0; i < count; i++)
|
||
clusterPixels[lightOff++] = indices[i];
|
||
freeSpace = false;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
var width = this._clusterTexture.width;
|
||
this._clusterTexture.setSubPixels(0, 0, width, Math.ceil(lightOff / (4 * width)), clusterPixels);
|
||
}
|
||
}
|
||
}
|
||
Cluster._tempVector30 = new Vector3();
|
||
Cluster._tempVector31 = new Vector3();
|
||
Cluster._tempVector32 = new Vector3();
|
||
Cluster._tempVector33 = new Vector3();
|
||
Cluster._tempVector34 = new Vector3();
|
||
Cluster._tempVector35 = new Vector3();
|
||
Cluster._tempVector36 = new Vector3();
|
||
Cluster._tempVector37 = new Vector3();
|
||
Cluster._tempLightBound = new LightBound();
|
||
|
||
class SphericalHarmonicsL2 {
|
||
constructor() {
|
||
this._coefficients = new Float32Array(27);
|
||
}
|
||
getCoefficient(i, j) {
|
||
return this._coefficients[i * 9 + j];
|
||
}
|
||
setCoefficient(i, j, coefficient) {
|
||
this._coefficients[i * 9 + j] = coefficient;
|
||
}
|
||
setCoefficients(i, coefficient0, coefficient1, coefficient2, coefficient3, coefficient4, coefficient5, coefficient6, coefficient7, coefficient8) {
|
||
var offset = i * 9;
|
||
this._coefficients[offset] = coefficient0;
|
||
this._coefficients[++offset] = coefficient1;
|
||
this._coefficients[++offset] = coefficient2;
|
||
this._coefficients[++offset] = coefficient3;
|
||
this._coefficients[++offset] = coefficient4;
|
||
this._coefficients[++offset] = coefficient5;
|
||
this._coefficients[++offset] = coefficient6;
|
||
this._coefficients[++offset] = coefficient7;
|
||
this._coefficients[++offset] = coefficient8;
|
||
}
|
||
cloneTo(dest) {
|
||
if (this === dest)
|
||
return;
|
||
var coes = this._coefficients;
|
||
var destCoes = dest._coefficients;
|
||
for (var i = 0; i < 27; i++)
|
||
destCoes[i] = coes[i];
|
||
}
|
||
}
|
||
SphericalHarmonicsL2._default = new SphericalHarmonicsL2();
|
||
|
||
class MouseTouch {
|
||
constructor() {
|
||
this._pressedSprite = null;
|
||
this._pressedLoopCount = -1;
|
||
this.sprite = null;
|
||
this.mousePositionX = 0;
|
||
this.mousePositionY = 0;
|
||
}
|
||
}
|
||
|
||
class Touch {
|
||
constructor() {
|
||
this._indexInList = -1;
|
||
this._identifier = -1;
|
||
this._position = new Vector2();
|
||
}
|
||
get identifier() {
|
||
return this._identifier;
|
||
}
|
||
get position() {
|
||
return this._position;
|
||
}
|
||
_getIndexInList() {
|
||
return this._indexInList;
|
||
}
|
||
_setIndexInList(index) {
|
||
this._indexInList = index;
|
||
}
|
||
}
|
||
|
||
class Plane {
|
||
constructor(normal, d = 0) {
|
||
this.normal = normal;
|
||
this.distance = d;
|
||
}
|
||
static createPlaneBy3P(point0, point1, point2, out) {
|
||
var x1 = point1.x - point0.x;
|
||
var y1 = point1.y - point0.y;
|
||
var z1 = point1.z - point0.z;
|
||
var x2 = point2.x - point0.x;
|
||
var y2 = point2.y - point0.y;
|
||
var z2 = point2.z - point0.z;
|
||
var yz = (y1 * z2) - (z1 * y2);
|
||
var xz = (z1 * x2) - (x1 * z2);
|
||
var xy = (x1 * y2) - (y1 * x2);
|
||
var invPyth = 1.0 / (Math.sqrt((yz * yz) + (xz * xz) + (xy * xy)));
|
||
var x = yz * invPyth;
|
||
var y = xz * invPyth;
|
||
var z = xy * invPyth;
|
||
var normal = out.normal;
|
||
normal.x = x;
|
||
normal.y = y;
|
||
normal.z = z;
|
||
out.distance = -((x * point0.x) + (y * point0.y) + (z * point0.z));
|
||
}
|
||
normalize() {
|
||
var normalEX = this.normal.x;
|
||
var normalEY = this.normal.y;
|
||
var normalEZ = this.normal.z;
|
||
var magnitude = 1.0 / Math.sqrt(normalEX * normalEX + normalEY * normalEY + normalEZ * normalEZ);
|
||
this.normal.x = normalEX * magnitude;
|
||
this.normal.y = normalEY * magnitude;
|
||
this.normal.z = normalEZ * magnitude;
|
||
this.distance *= magnitude;
|
||
}
|
||
cloneTo(destObject) {
|
||
var dest = destObject;
|
||
this.normal.cloneTo(dest.normal);
|
||
dest.distance = this.distance;
|
||
}
|
||
clone() {
|
||
var dest = new Plane(new Vector3());
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
}
|
||
Plane.PlaneIntersectionType_Back = 0;
|
||
Plane.PlaneIntersectionType_Front = 1;
|
||
Plane.PlaneIntersectionType_Intersecting = 2;
|
||
|
||
class Ray {
|
||
constructor(origin, direction) {
|
||
this.origin = origin;
|
||
this.direction = direction;
|
||
}
|
||
}
|
||
|
||
class ContainmentType {
|
||
}
|
||
ContainmentType.Disjoint = 0;
|
||
ContainmentType.Contains = 1;
|
||
ContainmentType.Intersects = 2;
|
||
|
||
class CollisionUtils {
|
||
constructor() {
|
||
}
|
||
static distancePlaneToPoint(plane, point) {
|
||
var dot = Vector3.dot(plane.normal, point);
|
||
return dot - plane.distance;
|
||
}
|
||
static distanceBoxToPoint(box, point) {
|
||
var boxMin = box.min;
|
||
var boxMineX = boxMin.x;
|
||
var boxMineY = boxMin.y;
|
||
var boxMineZ = boxMin.z;
|
||
var boxMax = box.max;
|
||
var boxMaxeX = boxMax.x;
|
||
var boxMaxeY = boxMax.y;
|
||
var boxMaxeZ = boxMax.z;
|
||
var pointeX = point.x;
|
||
var pointeY = point.y;
|
||
var pointeZ = point.z;
|
||
var distance = 0;
|
||
if (pointeX < boxMineX)
|
||
distance += (boxMineX - pointeX) * (boxMineX - pointeX);
|
||
if (pointeX > boxMaxeX)
|
||
distance += (boxMaxeX - pointeX) * (boxMaxeX - pointeX);
|
||
if (pointeY < boxMineY)
|
||
distance += (boxMineY - pointeY) * (boxMineY - pointeY);
|
||
if (pointeY > boxMaxeY)
|
||
distance += (boxMaxeY - pointeY) * (boxMaxeY - pointeY);
|
||
if (pointeZ < boxMineZ)
|
||
distance += (boxMineZ - pointeZ) * (boxMineZ - pointeZ);
|
||
if (pointeZ > boxMaxeZ)
|
||
distance += (boxMaxeZ - pointeZ) * (boxMaxeZ - pointeZ);
|
||
return Math.sqrt(distance);
|
||
}
|
||
static distanceBoxToBox(box1, box2) {
|
||
var box1Mine = box1.min;
|
||
var box1MineX = box1Mine.x;
|
||
var box1MineY = box1Mine.y;
|
||
var box1MineZ = box1Mine.z;
|
||
var box1Maxe = box1.max;
|
||
var box1MaxeX = box1Maxe.x;
|
||
var box1MaxeY = box1Maxe.y;
|
||
var box1MaxeZ = box1Maxe.z;
|
||
var box2Mine = box2.min;
|
||
var box2MineX = box2Mine.x;
|
||
var box2MineY = box2Mine.y;
|
||
var box2MineZ = box2Mine.z;
|
||
var box2Maxe = box2.max;
|
||
var box2MaxeX = box2Maxe.x;
|
||
var box2MaxeY = box2Maxe.y;
|
||
var box2MaxeZ = box2Maxe.z;
|
||
var distance = 0;
|
||
var delta;
|
||
if (box1MineX > box2MaxeX) {
|
||
delta = box1MineX - box2MaxeX;
|
||
distance += delta * delta;
|
||
}
|
||
else if (box2MineX > box1MaxeX) {
|
||
delta = box2MineX - box1MaxeX;
|
||
distance += delta * delta;
|
||
}
|
||
if (box1MineY > box2MaxeY) {
|
||
delta = box1MineY - box2MaxeY;
|
||
distance += delta * delta;
|
||
}
|
||
else if (box2MineY > box1MaxeY) {
|
||
delta = box2MineY - box1MaxeY;
|
||
distance += delta * delta;
|
||
}
|
||
if (box1MineZ > box2MaxeZ) {
|
||
delta = box1MineZ - box2MaxeZ;
|
||
distance += delta * delta;
|
||
}
|
||
else if (box2MineZ > box1MaxeZ) {
|
||
delta = box2MineZ - box1MaxeZ;
|
||
distance += delta * delta;
|
||
}
|
||
return Math.sqrt(distance);
|
||
}
|
||
static distanceSphereToPoint(sphere, point) {
|
||
var distance = Math.sqrt(Vector3.distanceSquared(sphere.center, point));
|
||
distance -= sphere.radius;
|
||
return Math.max(distance, 0);
|
||
}
|
||
static distanceSphereToSphere(sphere1, sphere2) {
|
||
var distance = Math.sqrt(Vector3.distanceSquared(sphere1.center, sphere2.center));
|
||
distance -= sphere1.radius + sphere2.radius;
|
||
return Math.max(distance, 0);
|
||
}
|
||
static intersectsRayAndTriangleRD(ray, vertex1, vertex2, vertex3, out) {
|
||
var rayO = ray.origin;
|
||
var rayOeX = rayO.x;
|
||
var rayOeY = rayO.y;
|
||
var rayOeZ = rayO.z;
|
||
var rayD = ray.direction;
|
||
var rayDeX = rayD.x;
|
||
var rayDeY = rayD.y;
|
||
var rayDeZ = rayD.z;
|
||
var v1eX = vertex1.x;
|
||
var v1eY = vertex1.y;
|
||
var v1eZ = vertex1.z;
|
||
var v2eX = vertex2.x;
|
||
var v2eY = vertex2.y;
|
||
var v2eZ = vertex2.z;
|
||
var v3eX = vertex3.x;
|
||
var v3eY = vertex3.y;
|
||
var v3eZ = vertex3.z;
|
||
var _tempV30eX = CollisionUtils._tempV30.x;
|
||
var _tempV30eY = CollisionUtils._tempV30.y;
|
||
var _tempV30eZ = CollisionUtils._tempV30.z;
|
||
_tempV30eX = v2eX - v1eX;
|
||
_tempV30eY = v2eY - v1eY;
|
||
_tempV30eZ = v2eZ - v1eZ;
|
||
var _tempV31eX = CollisionUtils._tempV31.x;
|
||
var _tempV31eY = CollisionUtils._tempV31.y;
|
||
var _tempV31eZ = CollisionUtils._tempV31.z;
|
||
_tempV31eX = v3eX - v1eX;
|
||
_tempV31eY = v3eY - v1eY;
|
||
_tempV31eZ = v3eZ - v1eZ;
|
||
var _tempV32eX = CollisionUtils._tempV32.x;
|
||
var _tempV32eY = CollisionUtils._tempV32.y;
|
||
var _tempV32eZ = CollisionUtils._tempV32.z;
|
||
_tempV32eX = (rayDeY * _tempV31eZ) - (rayDeZ * _tempV31eY);
|
||
_tempV32eY = (rayDeZ * _tempV31eX) - (rayDeX * _tempV31eZ);
|
||
_tempV32eZ = (rayDeX * _tempV31eY) - (rayDeY * _tempV31eX);
|
||
var determinant = (_tempV30eX * _tempV32eX) + (_tempV30eY * _tempV32eY) + (_tempV30eZ * _tempV32eZ);
|
||
if (MathUtils3D.isZero(determinant)) {
|
||
return false;
|
||
}
|
||
var inversedeterminant = 1 / determinant;
|
||
var _tempV33eX = CollisionUtils._tempV33.x;
|
||
var _tempV33eY = CollisionUtils._tempV33.y;
|
||
var _tempV33eZ = CollisionUtils._tempV33.z;
|
||
_tempV33eX = rayOeX - v1eX;
|
||
_tempV33eY = rayOeY - v1eY;
|
||
_tempV33eZ = rayOeZ - v1eZ;
|
||
var triangleU = (_tempV33eX * _tempV32eX) + (_tempV33eY * _tempV32eY) + (_tempV33eZ * _tempV32eZ);
|
||
triangleU *= inversedeterminant;
|
||
if (triangleU < 0 || triangleU > 1) {
|
||
return false;
|
||
}
|
||
var _tempV34eX = CollisionUtils._tempV34.x;
|
||
var _tempV34eY = CollisionUtils._tempV34.y;
|
||
var _tempV34eZ = CollisionUtils._tempV34.z;
|
||
_tempV34eX = (_tempV33eY * _tempV30eZ) - (_tempV33eZ * _tempV30eY);
|
||
_tempV34eY = (_tempV33eZ * _tempV30eX) - (_tempV33eX * _tempV30eZ);
|
||
_tempV34eZ = (_tempV33eX * _tempV30eY) - (_tempV33eY * _tempV30eX);
|
||
var triangleV = ((rayDeX * _tempV34eX) + (rayDeY * _tempV34eY)) + (rayDeZ * _tempV34eZ);
|
||
triangleV *= inversedeterminant;
|
||
if (triangleV < 0 || triangleU + triangleV > 1) {
|
||
return false;
|
||
}
|
||
var raydistance = (_tempV31eX * _tempV34eX) + (_tempV31eY * _tempV34eY) + (_tempV31eZ * _tempV34eZ);
|
||
raydistance *= inversedeterminant;
|
||
if (raydistance < 0) {
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
static intersectsRayAndTriangleRP(ray, vertex1, vertex2, vertex3, out) {
|
||
var distance;
|
||
if (!CollisionUtils.intersectsRayAndTriangleRD(ray, vertex1, vertex2, vertex3, distance)) {
|
||
out = Vector3._ZERO;
|
||
return false;
|
||
}
|
||
Vector3.scale(ray.direction, distance, CollisionUtils._tempV30);
|
||
Vector3.add(ray.origin, CollisionUtils._tempV30, out);
|
||
return true;
|
||
}
|
||
static intersectsRayAndPoint(ray, point) {
|
||
Vector3.subtract(ray.origin, point, CollisionUtils._tempV30);
|
||
var b = Vector3.dot(CollisionUtils._tempV30, ray.direction);
|
||
var c = Vector3.dot(CollisionUtils._tempV30, CollisionUtils._tempV30) - MathUtils3D.zeroTolerance;
|
||
if (c > 0 && b > 0)
|
||
return false;
|
||
var discriminant = b * b - c;
|
||
if (discriminant < 0)
|
||
return false;
|
||
return true;
|
||
}
|
||
static intersectsRayAndRay(ray1, ray2, out) {
|
||
var ray1o = ray1.origin;
|
||
var ray1oeX = ray1o.x;
|
||
var ray1oeY = ray1o.y;
|
||
var ray1oeZ = ray1o.z;
|
||
var ray1d = ray1.direction;
|
||
var ray1deX = ray1d.x;
|
||
var ray1deY = ray1d.y;
|
||
var ray1deZ = ray1d.z;
|
||
var ray2o = ray2.origin;
|
||
var ray2oeX = ray2o.x;
|
||
var ray2oeY = ray2o.y;
|
||
var ray2oeZ = ray2o.z;
|
||
var ray2d = ray2.direction;
|
||
var ray2deX = ray2d.x;
|
||
var ray2deY = ray2d.y;
|
||
var ray2deZ = ray2d.z;
|
||
Vector3.cross(ray1d, ray2d, CollisionUtils._tempV30);
|
||
var tempV3 = CollisionUtils._tempV30;
|
||
var denominator = Vector3.scalarLength(CollisionUtils._tempV30);
|
||
if (MathUtils3D.isZero(denominator)) {
|
||
if (MathUtils3D.nearEqual(ray2oeX, ray1oeX) && MathUtils3D.nearEqual(ray2oeY, ray1oeY) && MathUtils3D.nearEqual(ray2oeZ, ray1oeZ)) {
|
||
return true;
|
||
}
|
||
}
|
||
denominator = denominator * denominator;
|
||
var m11 = ray2oeX - ray1oeX;
|
||
var m12 = ray2oeY - ray1oeY;
|
||
var m13 = ray2oeZ - ray1oeZ;
|
||
var m21 = ray2deX;
|
||
var m22 = ray2deY;
|
||
var m23 = ray2deZ;
|
||
var m31 = tempV3.x;
|
||
var m32 = tempV3.y;
|
||
var m33 = tempV3.z;
|
||
var dets = m11 * m22 * m33 + m12 * m23 * m31 + m13 * m21 * m32 - m11 * m23 * m32 - m12 * m21 * m33 - m13 * m22 * m31;
|
||
m21 = ray1deX;
|
||
m22 = ray1deY;
|
||
m23 = ray1deZ;
|
||
var s = dets / denominator;
|
||
Vector3.scale(ray1d, s, CollisionUtils._tempV30);
|
||
Vector3.scale(ray2d, s, CollisionUtils._tempV31);
|
||
Vector3.add(ray1o, CollisionUtils._tempV30, CollisionUtils._tempV32);
|
||
Vector3.add(ray2o, CollisionUtils._tempV31, CollisionUtils._tempV33);
|
||
var point1e = CollisionUtils._tempV32;
|
||
var point2e = CollisionUtils._tempV33;
|
||
if (!MathUtils3D.nearEqual(point2e.x, point1e.x) || !MathUtils3D.nearEqual(point2e.y, point1e.y) || !MathUtils3D.nearEqual(point2e.z, point1e.z)) {
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
static intersectsPlaneAndTriangle(plane, vertex1, vertex2, vertex3) {
|
||
var test1 = CollisionUtils.intersectsPlaneAndPoint(plane, vertex1);
|
||
var test2 = CollisionUtils.intersectsPlaneAndPoint(plane, vertex2);
|
||
var test3 = CollisionUtils.intersectsPlaneAndPoint(plane, vertex3);
|
||
if (test1 == Plane.PlaneIntersectionType_Front && test2 == Plane.PlaneIntersectionType_Front && test3 == Plane.PlaneIntersectionType_Front)
|
||
return Plane.PlaneIntersectionType_Front;
|
||
if (test1 == Plane.PlaneIntersectionType_Back && test2 == Plane.PlaneIntersectionType_Back && test3 == Plane.PlaneIntersectionType_Back)
|
||
return Plane.PlaneIntersectionType_Back;
|
||
return Plane.PlaneIntersectionType_Intersecting;
|
||
}
|
||
static intersectsRayAndPlaneRD(ray, plane) {
|
||
var planeNor = plane.normal;
|
||
var direction = Vector3.dot(planeNor, ray.direction);
|
||
if (Math.abs(direction) < MathUtils3D.zeroTolerance)
|
||
return -1;
|
||
var position = Vector3.dot(planeNor, ray.origin);
|
||
var distance = (-plane.distance - position) / direction;
|
||
if (distance < 0) {
|
||
if (distance < -MathUtils3D.zeroTolerance)
|
||
return -1;
|
||
distance = 0;
|
||
}
|
||
return distance;
|
||
}
|
||
static intersectsRayAndPlaneRP(ray, plane, out) {
|
||
var distance = CollisionUtils.intersectsRayAndPlaneRD(ray, plane);
|
||
if (distance == -1) {
|
||
out.setValue(0, 0, 0);
|
||
return false;
|
||
}
|
||
var scaDis = CollisionUtils._tempV30;
|
||
Vector3.scale(ray.direction, distance, scaDis);
|
||
Vector3.add(ray.origin, scaDis, out);
|
||
return true;
|
||
}
|
||
static intersectsRayAndBoxRD(ray, box) {
|
||
var rayoe = ray.origin;
|
||
var rayoeX = rayoe.x;
|
||
var rayoeY = rayoe.y;
|
||
var rayoeZ = rayoe.z;
|
||
var rayde = ray.direction;
|
||
var raydeX = rayde.x;
|
||
var raydeY = rayde.y;
|
||
var raydeZ = rayde.z;
|
||
var boxMine = box.min;
|
||
var boxMineX = boxMine.x;
|
||
var boxMineY = boxMine.y;
|
||
var boxMineZ = boxMine.z;
|
||
var boxMaxe = box.max;
|
||
var boxMaxeX = boxMaxe.x;
|
||
var boxMaxeY = boxMaxe.y;
|
||
var boxMaxeZ = boxMaxe.z;
|
||
var out = 0;
|
||
var tmax = MathUtils3D.MaxValue;
|
||
if (MathUtils3D.isZero(raydeX)) {
|
||
if (rayoeX < boxMineX || rayoeX > boxMaxeX) {
|
||
return -1;
|
||
}
|
||
}
|
||
else {
|
||
var inverse = 1 / raydeX;
|
||
var t1 = (boxMineX - rayoeX) * inverse;
|
||
var t2 = (boxMaxeX - rayoeX) * inverse;
|
||
if (t1 > t2) {
|
||
var temp = t1;
|
||
t1 = t2;
|
||
t2 = temp;
|
||
}
|
||
out = Math.max(t1, out);
|
||
tmax = Math.min(t2, tmax);
|
||
if (out > tmax) {
|
||
return -1;
|
||
}
|
||
}
|
||
if (MathUtils3D.isZero(raydeY)) {
|
||
if (rayoeY < boxMineY || rayoeY > boxMaxeY) {
|
||
return -1;
|
||
}
|
||
}
|
||
else {
|
||
var inverse1 = 1 / raydeY;
|
||
var t3 = (boxMineY - rayoeY) * inverse1;
|
||
var t4 = (boxMaxeY - rayoeY) * inverse1;
|
||
if (t3 > t4) {
|
||
var temp1 = t3;
|
||
t3 = t4;
|
||
t4 = temp1;
|
||
}
|
||
out = Math.max(t3, out);
|
||
tmax = Math.min(t4, tmax);
|
||
if (out > tmax) {
|
||
return -1;
|
||
}
|
||
}
|
||
if (MathUtils3D.isZero(raydeZ)) {
|
||
if (rayoeZ < boxMineZ || rayoeZ > boxMaxeZ) {
|
||
return -1;
|
||
}
|
||
}
|
||
else {
|
||
var inverse2 = 1 / raydeZ;
|
||
var t5 = (boxMineZ - rayoeZ) * inverse2;
|
||
var t6 = (boxMaxeZ - rayoeZ) * inverse2;
|
||
if (t5 > t6) {
|
||
var temp2 = t5;
|
||
t5 = t6;
|
||
t6 = temp2;
|
||
}
|
||
out = Math.max(t5, out);
|
||
tmax = Math.min(t6, tmax);
|
||
if (out > tmax) {
|
||
return -1;
|
||
}
|
||
}
|
||
return out;
|
||
}
|
||
static intersectsRayAndBoxRP(ray, box, out) {
|
||
var distance = CollisionUtils.intersectsRayAndBoxRD(ray, box);
|
||
if (distance === -1) {
|
||
Vector3._ZERO.cloneTo(out);
|
||
return distance;
|
||
}
|
||
Vector3.scale(ray.direction, distance, CollisionUtils._tempV30);
|
||
Vector3.add(ray.origin, CollisionUtils._tempV30, CollisionUtils._tempV31);
|
||
CollisionUtils._tempV31.cloneTo(out);
|
||
return distance;
|
||
}
|
||
static intersectsRayAndSphereRD(ray, sphere) {
|
||
var sphereR = sphere.radius;
|
||
Vector3.subtract(ray.origin, sphere.center, CollisionUtils._tempV30);
|
||
var b = Vector3.dot(CollisionUtils._tempV30, ray.direction);
|
||
var c = Vector3.dot(CollisionUtils._tempV30, CollisionUtils._tempV30) - (sphereR * sphereR);
|
||
if (c > 0 && b > 0) {
|
||
return -1;
|
||
}
|
||
var discriminant = b * b - c;
|
||
if (discriminant < 0) {
|
||
return -1;
|
||
}
|
||
var distance = -b - Math.sqrt(discriminant);
|
||
if (distance < 0)
|
||
distance = 0;
|
||
return distance;
|
||
}
|
||
static intersectsRayAndSphereRP(ray, sphere, out) {
|
||
var distance = CollisionUtils.intersectsRayAndSphereRD(ray, sphere);
|
||
if (distance === -1) {
|
||
Vector3._ZERO.cloneTo(out);
|
||
return distance;
|
||
}
|
||
Vector3.scale(ray.direction, distance, CollisionUtils._tempV30);
|
||
Vector3.add(ray.origin, CollisionUtils._tempV30, CollisionUtils._tempV31);
|
||
CollisionUtils._tempV31.cloneTo(out);
|
||
return distance;
|
||
}
|
||
static intersectsSphereAndTriangle(sphere, vertex1, vertex2, vertex3) {
|
||
var sphereC = sphere.center;
|
||
var sphereR = sphere.radius;
|
||
CollisionUtils.closestPointPointTriangle(sphereC, vertex1, vertex2, vertex3, CollisionUtils._tempV30);
|
||
Vector3.subtract(CollisionUtils._tempV30, sphereC, CollisionUtils._tempV31);
|
||
var dot = Vector3.dot(CollisionUtils._tempV31, CollisionUtils._tempV31);
|
||
return dot <= sphereR * sphereR;
|
||
}
|
||
static intersectsPlaneAndPoint(plane, point) {
|
||
var distance = Vector3.dot(plane.normal, point) + plane.distance;
|
||
if (distance > 0)
|
||
return Plane.PlaneIntersectionType_Front;
|
||
if (distance < 0)
|
||
return Plane.PlaneIntersectionType_Back;
|
||
return Plane.PlaneIntersectionType_Intersecting;
|
||
}
|
||
static intersectsPlaneAndPlane(plane1, plane2) {
|
||
Vector3.cross(plane1.normal, plane2.normal, CollisionUtils._tempV30);
|
||
var denominator = Vector3.dot(CollisionUtils._tempV30, CollisionUtils._tempV30);
|
||
if (MathUtils3D.isZero(denominator))
|
||
return false;
|
||
return true;
|
||
}
|
||
static intersectsPlaneAndPlaneRL(plane1, plane2, line) {
|
||
var plane1nor = plane1.normal;
|
||
var plane2nor = plane2.normal;
|
||
Vector3.cross(plane1nor, plane2nor, CollisionUtils._tempV34);
|
||
var denominator = Vector3.dot(CollisionUtils._tempV34, CollisionUtils._tempV34);
|
||
if (MathUtils3D.isZero(denominator))
|
||
return false;
|
||
Vector3.scale(plane2nor, plane1.distance, CollisionUtils._tempV30);
|
||
Vector3.scale(plane1nor, plane2.distance, CollisionUtils._tempV31);
|
||
Vector3.subtract(CollisionUtils._tempV30, CollisionUtils._tempV31, CollisionUtils._tempV32);
|
||
Vector3.cross(CollisionUtils._tempV32, CollisionUtils._tempV34, CollisionUtils._tempV33);
|
||
Vector3.normalize(CollisionUtils._tempV34, CollisionUtils._tempV34);
|
||
return true;
|
||
}
|
||
static intersectsPlaneAndBox(plane, box) {
|
||
var planeD = plane.distance;
|
||
var planeNor = plane.normal;
|
||
var planeNoreX = planeNor.x;
|
||
var planeNoreY = planeNor.y;
|
||
var planeNoreZ = planeNor.z;
|
||
var boxMine = box.min;
|
||
var boxMineX = boxMine.x;
|
||
var boxMineY = boxMine.y;
|
||
var boxMineZ = boxMine.z;
|
||
var boxMaxe = box.max;
|
||
var boxMaxeX = boxMaxe.x;
|
||
var boxMaxeY = boxMaxe.y;
|
||
var boxMaxeZ = boxMaxe.z;
|
||
CollisionUtils._tempV30.x = (planeNoreX > 0) ? boxMineX : boxMaxeX;
|
||
CollisionUtils._tempV30.y = (planeNoreY > 0) ? boxMineY : boxMaxeY;
|
||
CollisionUtils._tempV30.z = (planeNoreZ > 0) ? boxMineZ : boxMaxeZ;
|
||
CollisionUtils._tempV31.x = (planeNoreX > 0) ? boxMaxeX : boxMineX;
|
||
CollisionUtils._tempV31.y = (planeNoreY > 0) ? boxMaxeY : boxMineY;
|
||
CollisionUtils._tempV31.z = (planeNoreZ > 0) ? boxMaxeZ : boxMineZ;
|
||
var distance = Vector3.dot(planeNor, CollisionUtils._tempV30);
|
||
if (distance + planeD > 0)
|
||
return Plane.PlaneIntersectionType_Front;
|
||
distance = Vector3.dot(planeNor, CollisionUtils._tempV31);
|
||
if (distance + planeD < 0)
|
||
return Plane.PlaneIntersectionType_Back;
|
||
return Plane.PlaneIntersectionType_Intersecting;
|
||
}
|
||
static intersectsPlaneAndSphere(plane, sphere) {
|
||
var sphereR = sphere.radius;
|
||
var distance = Vector3.dot(plane.normal, sphere.center) + plane.distance;
|
||
if (distance > sphereR)
|
||
return Plane.PlaneIntersectionType_Front;
|
||
if (distance < -sphereR)
|
||
return Plane.PlaneIntersectionType_Back;
|
||
return Plane.PlaneIntersectionType_Intersecting;
|
||
}
|
||
static intersectsBoxAndBox(box1, box2) {
|
||
var box1Mine = box1.min;
|
||
var box1Maxe = box1.max;
|
||
var box2Mine = box2.min;
|
||
var box2Maxe = box2.max;
|
||
if (box1Mine.x > box2Maxe.x || box2Mine.x > box1Maxe.x)
|
||
return false;
|
||
if (box1Mine.y > box2Maxe.y || box2Mine.y > box1Maxe.y)
|
||
return false;
|
||
if (box1Mine.z > box2Maxe.z || box2Mine.z > box1Maxe.z)
|
||
return false;
|
||
return true;
|
||
}
|
||
static intersectsBoxAndSphere(box, sphere) {
|
||
var center = sphere.center;
|
||
var radius = sphere.radius;
|
||
var nearest = CollisionUtils._tempV30;
|
||
Vector3.Clamp(center, box.min, box.max, nearest);
|
||
var distance = Vector3.distanceSquared(center, nearest);
|
||
return distance <= radius * radius;
|
||
}
|
||
static intersectsSphereAndSphere(sphere1, sphere2) {
|
||
var radiisum = sphere1.radius + sphere2.radius;
|
||
return Vector3.distanceSquared(sphere1.center, sphere2.center) <= radiisum * radiisum;
|
||
}
|
||
static boxContainsPoint(box, point) {
|
||
var boxMine = box.min;
|
||
var boxMaxe = box.max;
|
||
if (boxMine.x <= point.x && boxMaxe.x >= point.x && boxMine.y <= point.y && boxMaxe.y >= point.y && boxMine.z <= point.z && boxMaxe.z >= point.z)
|
||
return ContainmentType.Contains;
|
||
return ContainmentType.Disjoint;
|
||
}
|
||
static boxContainsBox(box1, box2) {
|
||
var box1Mine = box1.min;
|
||
var box1MineX = box1Mine.x;
|
||
var box1MineY = box1Mine.y;
|
||
var box1MineZ = box1Mine.z;
|
||
var box1Maxe = box1.max;
|
||
var box1MaxeX = box1Maxe.x;
|
||
var box1MaxeY = box1Maxe.y;
|
||
var box1MaxeZ = box1Maxe.z;
|
||
var box2Mine = box2.min;
|
||
var box2MineX = box2Mine.x;
|
||
var box2MineY = box2Mine.y;
|
||
var box2MineZ = box2Mine.z;
|
||
var box2Maxe = box2.max;
|
||
var box2MaxeX = box2Maxe.x;
|
||
var box2MaxeY = box2Maxe.y;
|
||
var box2MaxeZ = box2Maxe.z;
|
||
if (box1MaxeX < box2MineX || box1MineX > box2MaxeX)
|
||
return ContainmentType.Disjoint;
|
||
if (box1MaxeY < box2MineY || box1MineY > box2MaxeY)
|
||
return ContainmentType.Disjoint;
|
||
if (box1MaxeZ < box2MineZ || box1MineZ > box2MaxeZ)
|
||
return ContainmentType.Disjoint;
|
||
if (box1MineX <= box2MineX && box2MaxeX <= box1MaxeX && box1MineY <= box2MineY && box2MaxeY <= box1MaxeY && box1MineZ <= box2MineZ && box2MaxeZ <= box1MaxeZ) {
|
||
return ContainmentType.Contains;
|
||
}
|
||
return ContainmentType.Intersects;
|
||
}
|
||
static boxContainsSphere(box, sphere) {
|
||
var boxMin = box.min;
|
||
var boxMineX = boxMin.x;
|
||
var boxMineY = boxMin.y;
|
||
var boxMineZ = boxMin.z;
|
||
var boxMax = box.max;
|
||
var boxMaxeX = boxMax.x;
|
||
var boxMaxeY = boxMax.y;
|
||
var boxMaxeZ = boxMax.z;
|
||
var sphereC = sphere.center;
|
||
var sphereCeX = sphereC.x;
|
||
var sphereCeY = sphereC.y;
|
||
var sphereCeZ = sphereC.z;
|
||
var sphereR = sphere.radius;
|
||
Vector3.Clamp(sphereC, boxMin, boxMax, CollisionUtils._tempV30);
|
||
var distance = Vector3.distanceSquared(sphereC, CollisionUtils._tempV30);
|
||
if (distance > sphereR * sphereR)
|
||
return ContainmentType.Disjoint;
|
||
if ((((boxMineX + sphereR <= sphereCeX) && (sphereCeX <= boxMaxeX - sphereR)) && ((boxMaxeX - boxMineX > sphereR) &&
|
||
(boxMineY + sphereR <= sphereCeY))) && (((sphereCeY <= boxMaxeY - sphereR) && (boxMaxeY - boxMineY > sphereR)) &&
|
||
(((boxMineZ + sphereR <= sphereCeZ) && (sphereCeZ <= boxMaxeZ - sphereR)) && (boxMaxeZ - boxMineZ > sphereR))))
|
||
return ContainmentType.Contains;
|
||
return ContainmentType.Intersects;
|
||
}
|
||
static sphereContainsPoint(sphere, point) {
|
||
if (Vector3.distanceSquared(point, sphere.center) <= sphere.radius * sphere.radius)
|
||
return ContainmentType.Contains;
|
||
return ContainmentType.Disjoint;
|
||
}
|
||
static sphereContainsTriangle(sphere, vertex1, vertex2, vertex3) {
|
||
var test1 = CollisionUtils.sphereContainsPoint(sphere, vertex1);
|
||
var test2 = CollisionUtils.sphereContainsPoint(sphere, vertex2);
|
||
var test3 = CollisionUtils.sphereContainsPoint(sphere, vertex3);
|
||
if (test1 == ContainmentType.Contains && test2 == ContainmentType.Contains && test3 == ContainmentType.Contains)
|
||
return ContainmentType.Contains;
|
||
if (CollisionUtils.intersectsSphereAndTriangle(sphere, vertex1, vertex2, vertex3))
|
||
return ContainmentType.Intersects;
|
||
return ContainmentType.Disjoint;
|
||
}
|
||
static sphereContainsBox(sphere, box) {
|
||
var sphereC = sphere.center;
|
||
var sphereCeX = sphereC.x;
|
||
var sphereCeY = sphereC.y;
|
||
var sphereCeZ = sphereC.z;
|
||
var sphereR = sphere.radius;
|
||
var boxMin = box.min;
|
||
var boxMineX = boxMin.x;
|
||
var boxMineY = boxMin.y;
|
||
var boxMineZ = boxMin.z;
|
||
var boxMax = box.max;
|
||
var boxMaxeX = boxMax.x;
|
||
var boxMaxeY = boxMax.y;
|
||
var boxMaxeZ = boxMax.z;
|
||
var _tempV30e = CollisionUtils._tempV30;
|
||
var _tempV30eX = _tempV30e.x;
|
||
var _tempV30eY = _tempV30e.y;
|
||
var _tempV30eZ = _tempV30e.z;
|
||
if (!CollisionUtils.intersectsBoxAndSphere(box, sphere))
|
||
return ContainmentType.Disjoint;
|
||
var radiusSquared = sphereR * sphereR;
|
||
_tempV30eX = sphereCeX - boxMineX;
|
||
_tempV30eY = sphereCeY - boxMaxeY;
|
||
_tempV30eZ = sphereCeZ - boxMaxeZ;
|
||
if (Vector3.scalarLengthSquared(CollisionUtils._tempV30) > radiusSquared)
|
||
return ContainmentType.Intersects;
|
||
_tempV30eX = sphereCeX - boxMaxeX;
|
||
_tempV30eY = sphereCeY - boxMaxeY;
|
||
_tempV30eZ = sphereCeZ - boxMaxeZ;
|
||
if (Vector3.scalarLengthSquared(CollisionUtils._tempV30) > radiusSquared)
|
||
return ContainmentType.Intersects;
|
||
_tempV30eX = sphereCeX - boxMaxeX;
|
||
_tempV30eY = sphereCeY - boxMineY;
|
||
_tempV30eZ = sphereCeZ - boxMaxeZ;
|
||
if (Vector3.scalarLengthSquared(CollisionUtils._tempV30) > radiusSquared)
|
||
return ContainmentType.Intersects;
|
||
_tempV30eX = sphereCeX - boxMineX;
|
||
_tempV30eY = sphereCeY - boxMineY;
|
||
_tempV30eZ = sphereCeZ - boxMaxeZ;
|
||
if (Vector3.scalarLengthSquared(CollisionUtils._tempV30) > radiusSquared)
|
||
return ContainmentType.Intersects;
|
||
_tempV30eX = sphereCeX - boxMineX;
|
||
_tempV30eY = sphereCeY - boxMaxeY;
|
||
_tempV30eZ = sphereCeZ - boxMineZ;
|
||
if (Vector3.scalarLengthSquared(CollisionUtils._tempV30) > radiusSquared)
|
||
return ContainmentType.Intersects;
|
||
_tempV30eX = sphereCeX - boxMaxeX;
|
||
_tempV30eY = sphereCeY - boxMaxeY;
|
||
_tempV30eZ = sphereCeZ - boxMineZ;
|
||
if (Vector3.scalarLengthSquared(CollisionUtils._tempV30) > radiusSquared)
|
||
return ContainmentType.Intersects;
|
||
_tempV30eX = sphereCeX - boxMaxeX;
|
||
_tempV30eY = sphereCeY - boxMineY;
|
||
_tempV30eZ = sphereCeZ - boxMineZ;
|
||
if (Vector3.scalarLengthSquared(CollisionUtils._tempV30) > radiusSquared)
|
||
return ContainmentType.Intersects;
|
||
_tempV30eX = sphereCeX - boxMineX;
|
||
_tempV30eY = sphereCeY - boxMineY;
|
||
_tempV30eZ = sphereCeZ - boxMineZ;
|
||
if (Vector3.scalarLengthSquared(CollisionUtils._tempV30) > radiusSquared)
|
||
return ContainmentType.Intersects;
|
||
return ContainmentType.Contains;
|
||
}
|
||
static sphereContainsSphere(sphere1, sphere2) {
|
||
var sphere1R = sphere1.radius;
|
||
var sphere2R = sphere2.radius;
|
||
var distance = Vector3.distance(sphere1.center, sphere2.center);
|
||
if (sphere1R + sphere2R < distance)
|
||
return ContainmentType.Disjoint;
|
||
if (sphere1R - sphere2R < distance)
|
||
return ContainmentType.Intersects;
|
||
return ContainmentType.Contains;
|
||
}
|
||
static closestPointPointTriangle(point, vertex1, vertex2, vertex3, out) {
|
||
Vector3.subtract(vertex2, vertex1, CollisionUtils._tempV30);
|
||
Vector3.subtract(vertex3, vertex1, CollisionUtils._tempV31);
|
||
Vector3.subtract(point, vertex1, CollisionUtils._tempV32);
|
||
Vector3.subtract(point, vertex2, CollisionUtils._tempV33);
|
||
Vector3.subtract(point, vertex3, CollisionUtils._tempV34);
|
||
var d1 = Vector3.dot(CollisionUtils._tempV30, CollisionUtils._tempV32);
|
||
var d2 = Vector3.dot(CollisionUtils._tempV31, CollisionUtils._tempV32);
|
||
var d3 = Vector3.dot(CollisionUtils._tempV30, CollisionUtils._tempV33);
|
||
var d4 = Vector3.dot(CollisionUtils._tempV31, CollisionUtils._tempV33);
|
||
var d5 = Vector3.dot(CollisionUtils._tempV30, CollisionUtils._tempV34);
|
||
var d6 = Vector3.dot(CollisionUtils._tempV31, CollisionUtils._tempV34);
|
||
if (d1 <= 0 && d2 <= 0) {
|
||
vertex1.cloneTo(out);
|
||
return;
|
||
}
|
||
if (d3 >= 0 && d4 <= d3) {
|
||
vertex2.cloneTo(out);
|
||
return;
|
||
}
|
||
var vc = d1 * d4 - d3 * d2;
|
||
if (vc <= 0 && d1 >= 0 && d3 <= 0) {
|
||
var v = d1 / (d1 - d3);
|
||
Vector3.scale(CollisionUtils._tempV30, v, out);
|
||
Vector3.add(vertex1, out, out);
|
||
return;
|
||
}
|
||
if (d6 >= 0 && d5 <= d6) {
|
||
vertex3.cloneTo(out);
|
||
return;
|
||
}
|
||
var vb = d5 * d2 - d1 * d6;
|
||
if (vb <= 0 && d2 >= 0 && d6 <= 0) {
|
||
var w = d2 / (d2 - d6);
|
||
Vector3.scale(CollisionUtils._tempV31, w, out);
|
||
Vector3.add(vertex1, out, out);
|
||
return;
|
||
}
|
||
var va = d3 * d6 - d5 * d4;
|
||
if (va <= 0 && (d4 - d3) >= 0 && (d5 - d6) >= 0) {
|
||
var w3 = (d4 - d3) / ((d4 - d3) + (d5 - d6));
|
||
Vector3.subtract(vertex3, vertex2, out);
|
||
Vector3.scale(out, w3, out);
|
||
Vector3.add(vertex2, out, out);
|
||
return;
|
||
}
|
||
var denom = 1 / (va + vb + vc);
|
||
var v2 = vb * denom;
|
||
var w2 = vc * denom;
|
||
Vector3.scale(CollisionUtils._tempV30, v2, CollisionUtils._tempV35);
|
||
Vector3.scale(CollisionUtils._tempV31, w2, CollisionUtils._tempV36);
|
||
Vector3.add(CollisionUtils._tempV35, CollisionUtils._tempV36, out);
|
||
Vector3.add(vertex1, out, out);
|
||
}
|
||
static closestPointPlanePoint(plane, point, out) {
|
||
var planeN = plane.normal;
|
||
var t = Vector3.dot(planeN, point) - plane.distance;
|
||
Vector3.scale(planeN, t, CollisionUtils._tempV30);
|
||
Vector3.subtract(point, CollisionUtils._tempV30, out);
|
||
}
|
||
static closestPointBoxPoint(box, point, out) {
|
||
Vector3.max(point, box.min, CollisionUtils._tempV30);
|
||
Vector3.min(CollisionUtils._tempV30, box.max, out);
|
||
}
|
||
static closestPointSpherePoint(sphere, point, out) {
|
||
var sphereC = sphere.center;
|
||
Vector3.subtract(point, sphereC, out);
|
||
Vector3.normalize(out, out);
|
||
Vector3.scale(out, sphere.radius, out);
|
||
Vector3.add(out, sphereC, out);
|
||
}
|
||
static closestPointSphereSphere(sphere1, sphere2, out) {
|
||
var sphere1C = sphere1.center;
|
||
Vector3.subtract(sphere2.center, sphere1C, out);
|
||
Vector3.normalize(out, out);
|
||
Vector3.scale(out, sphere1.radius, out);
|
||
Vector3.add(out, sphere1C, out);
|
||
}
|
||
}
|
||
CollisionUtils._tempV30 = new Vector3();
|
||
CollisionUtils._tempV31 = new Vector3();
|
||
CollisionUtils._tempV32 = new Vector3();
|
||
CollisionUtils._tempV33 = new Vector3();
|
||
CollisionUtils._tempV34 = new Vector3();
|
||
CollisionUtils._tempV35 = new Vector3();
|
||
CollisionUtils._tempV36 = new Vector3();
|
||
|
||
(function (FrustumCorner) {
|
||
FrustumCorner[FrustumCorner["FarBottomLeft"] = 0] = "FarBottomLeft";
|
||
FrustumCorner[FrustumCorner["FarTopLeft"] = 1] = "FarTopLeft";
|
||
FrustumCorner[FrustumCorner["FarTopRight"] = 2] = "FarTopRight";
|
||
FrustumCorner[FrustumCorner["FarBottomRight"] = 3] = "FarBottomRight";
|
||
FrustumCorner[FrustumCorner["nearBottomLeft"] = 4] = "nearBottomLeft";
|
||
FrustumCorner[FrustumCorner["nearTopLeft"] = 5] = "nearTopLeft";
|
||
FrustumCorner[FrustumCorner["nearTopRight"] = 6] = "nearTopRight";
|
||
FrustumCorner[FrustumCorner["nearBottomRight"] = 7] = "nearBottomRight";
|
||
FrustumCorner[FrustumCorner["unknown"] = 8] = "unknown";
|
||
})(exports.FrustumCorner || (exports.FrustumCorner = {}));
|
||
class BoundFrustum {
|
||
constructor(matrix) {
|
||
this._matrix = matrix;
|
||
this._near = new Plane(new Vector3());
|
||
this._far = new Plane(new Vector3());
|
||
this._left = new Plane(new Vector3());
|
||
this._right = new Plane(new Vector3());
|
||
this._top = new Plane(new Vector3());
|
||
this._bottom = new Plane(new Vector3());
|
||
BoundFrustum.getPlanesFromMatrix(this._matrix, this._near, this._far, this._left, this._right, this._top, this._bottom);
|
||
}
|
||
static getPlanesFromMatrix(m, np, fp, lp, rp, tp, bp) {
|
||
var matrixE = m.elements;
|
||
var m11 = matrixE[0];
|
||
var m12 = matrixE[1];
|
||
var m13 = matrixE[2];
|
||
var m14 = matrixE[3];
|
||
var m21 = matrixE[4];
|
||
var m22 = matrixE[5];
|
||
var m23 = matrixE[6];
|
||
var m24 = matrixE[7];
|
||
var m31 = matrixE[8];
|
||
var m32 = matrixE[9];
|
||
var m33 = matrixE[10];
|
||
var m34 = matrixE[11];
|
||
var m41 = matrixE[12];
|
||
var m42 = matrixE[13];
|
||
var m43 = matrixE[14];
|
||
var m44 = matrixE[15];
|
||
var nearNorE = np.normal;
|
||
nearNorE.x = m13;
|
||
nearNorE.y = m23;
|
||
nearNorE.z = m33;
|
||
np.distance = m43;
|
||
np.normalize();
|
||
var farNorE = fp.normal;
|
||
farNorE.x = m14 - m13;
|
||
farNorE.y = m24 - m23;
|
||
farNorE.z = m34 - m33;
|
||
fp.distance = m44 - m43;
|
||
fp.normalize();
|
||
var leftNorE = lp.normal;
|
||
leftNorE.x = m14 + m11;
|
||
leftNorE.y = m24 + m21;
|
||
leftNorE.z = m34 + m31;
|
||
lp.distance = m44 + m41;
|
||
lp.normalize();
|
||
var rightNorE = rp.normal;
|
||
rightNorE.x = m14 - m11;
|
||
rightNorE.y = m24 - m21;
|
||
rightNorE.z = m34 - m31;
|
||
rp.distance = m44 - m41;
|
||
rp.normalize();
|
||
var topNorE = tp.normal;
|
||
topNorE.x = m14 - m12;
|
||
topNorE.y = m24 - m22;
|
||
topNorE.z = m34 - m32;
|
||
tp.distance = m44 - m42;
|
||
tp.normalize();
|
||
var bottomNorE = bp.normal;
|
||
bottomNorE.x = m14 + m12;
|
||
bottomNorE.y = m24 + m22;
|
||
bottomNorE.z = m34 + m32;
|
||
bp.distance = m44 + m42;
|
||
bp.normalize();
|
||
}
|
||
get matrix() {
|
||
return this._matrix;
|
||
}
|
||
set matrix(matrix) {
|
||
matrix.cloneTo(this._matrix);
|
||
BoundFrustum.getPlanesFromMatrix(this._matrix, this._near, this._far, this._left, this._right, this._top, this._bottom);
|
||
}
|
||
get near() {
|
||
return this._near;
|
||
}
|
||
get far() {
|
||
return this._far;
|
||
}
|
||
get left() {
|
||
return this._left;
|
||
}
|
||
get right() {
|
||
return this._right;
|
||
}
|
||
get top() {
|
||
return this._top;
|
||
}
|
||
get bottom() {
|
||
return this._bottom;
|
||
}
|
||
equalsBoundFrustum(other) {
|
||
return this._matrix.equalsOtherMatrix(other.matrix);
|
||
}
|
||
equalsObj(obj) {
|
||
if (obj instanceof BoundFrustum) {
|
||
var bf = obj;
|
||
return this.equalsBoundFrustum(bf);
|
||
}
|
||
return false;
|
||
}
|
||
getPlane(index) {
|
||
switch (index) {
|
||
case 0:
|
||
return this._near;
|
||
case 1:
|
||
return this._far;
|
||
case 2:
|
||
return this._left;
|
||
case 3:
|
||
return this._right;
|
||
case 4:
|
||
return this._top;
|
||
case 5:
|
||
return this._bottom;
|
||
default:
|
||
return null;
|
||
}
|
||
}
|
||
static get3PlaneInterPoint(p1, p2, p3, out) {
|
||
var p1Nor = p1.normal;
|
||
var p2Nor = p2.normal;
|
||
var p3Nor = p3.normal;
|
||
Vector3.cross(p2Nor, p3Nor, BoundFrustum._tempV30);
|
||
Vector3.cross(p3Nor, p1Nor, BoundFrustum._tempV31);
|
||
Vector3.cross(p1Nor, p2Nor, BoundFrustum._tempV32);
|
||
var a = Vector3.dot(p1Nor, BoundFrustum._tempV30);
|
||
var b = Vector3.dot(p2Nor, BoundFrustum._tempV31);
|
||
var c = Vector3.dot(p3Nor, BoundFrustum._tempV32);
|
||
Vector3.scale(BoundFrustum._tempV30, -p1.distance / a, BoundFrustum._tempV33);
|
||
Vector3.scale(BoundFrustum._tempV31, -p2.distance / b, BoundFrustum._tempV34);
|
||
Vector3.scale(BoundFrustum._tempV32, -p3.distance / c, BoundFrustum._tempV35);
|
||
Vector3.add(BoundFrustum._tempV33, BoundFrustum._tempV34, BoundFrustum._tempV36);
|
||
Vector3.add(BoundFrustum._tempV35, BoundFrustum._tempV36, out);
|
||
}
|
||
getCorners(corners) {
|
||
BoundFrustum.get3PlaneInterPoint(this._near, this._bottom, this._right, corners[exports.FrustumCorner.nearBottomRight]);
|
||
BoundFrustum.get3PlaneInterPoint(this._near, this._top, this._right, corners[exports.FrustumCorner.nearTopRight]);
|
||
BoundFrustum.get3PlaneInterPoint(this._near, this._top, this._left, corners[exports.FrustumCorner.nearTopLeft]);
|
||
BoundFrustum.get3PlaneInterPoint(this._near, this._bottom, this._left, corners[exports.FrustumCorner.nearBottomLeft]);
|
||
BoundFrustum.get3PlaneInterPoint(this._far, this._bottom, this._right, corners[exports.FrustumCorner.FarBottomRight]);
|
||
BoundFrustum.get3PlaneInterPoint(this._far, this._top, this._right, corners[exports.FrustumCorner.FarTopRight]);
|
||
BoundFrustum.get3PlaneInterPoint(this._far, this._top, this._left, corners[exports.FrustumCorner.FarTopLeft]);
|
||
BoundFrustum.get3PlaneInterPoint(this._far, this._bottom, this._left, corners[exports.FrustumCorner.FarBottomLeft]);
|
||
}
|
||
containsPoint(point) {
|
||
var result = Plane.PlaneIntersectionType_Front;
|
||
var planeResult = Plane.PlaneIntersectionType_Front;
|
||
for (var i = 0; i < 6; i++) {
|
||
switch (i) {
|
||
case 0:
|
||
planeResult = CollisionUtils.intersectsPlaneAndPoint(this._near, point);
|
||
break;
|
||
case 1:
|
||
planeResult = CollisionUtils.intersectsPlaneAndPoint(this._far, point);
|
||
break;
|
||
case 2:
|
||
planeResult = CollisionUtils.intersectsPlaneAndPoint(this._left, point);
|
||
break;
|
||
case 3:
|
||
planeResult = CollisionUtils.intersectsPlaneAndPoint(this._right, point);
|
||
break;
|
||
case 4:
|
||
planeResult = CollisionUtils.intersectsPlaneAndPoint(this._top, point);
|
||
break;
|
||
case 5:
|
||
planeResult = CollisionUtils.intersectsPlaneAndPoint(this._bottom, point);
|
||
break;
|
||
}
|
||
switch (planeResult) {
|
||
case Plane.PlaneIntersectionType_Back:
|
||
return ContainmentType.Disjoint;
|
||
case Plane.PlaneIntersectionType_Intersecting:
|
||
result = Plane.PlaneIntersectionType_Intersecting;
|
||
break;
|
||
}
|
||
}
|
||
switch (result) {
|
||
case Plane.PlaneIntersectionType_Intersecting:
|
||
return ContainmentType.Intersects;
|
||
default:
|
||
return ContainmentType.Contains;
|
||
}
|
||
}
|
||
intersects(box) {
|
||
var min = box.min;
|
||
var max = box.max;
|
||
var minX = min.x;
|
||
var minY = min.y;
|
||
var minZ = min.z;
|
||
var maxX = max.x;
|
||
var maxY = max.y;
|
||
var maxZ = max.z;
|
||
var nearNormal = this._near.normal;
|
||
if (this._near.distance + (nearNormal.x * (nearNormal.x < 0 ? minX : maxX)) + (nearNormal.y * (nearNormal.y < 0 ? minY : maxY)) + (nearNormal.z * (nearNormal.z < 0 ? minZ : maxZ)) < 0)
|
||
return false;
|
||
var leftNormal = this._left.normal;
|
||
if (this._left.distance + (leftNormal.x * (leftNormal.x < 0 ? minX : maxX)) + (leftNormal.y * (leftNormal.y < 0 ? minY : maxY)) + (leftNormal.z * (leftNormal.z < 0 ? minZ : maxZ)) < 0)
|
||
return false;
|
||
var rightNormal = this._right.normal;
|
||
if (this._right.distance + (rightNormal.x * (rightNormal.x < 0 ? minX : maxX)) + (rightNormal.y * (rightNormal.y < 0 ? minY : maxY)) + (rightNormal.z * (rightNormal.z < 0 ? minZ : maxZ)) < 0)
|
||
return false;
|
||
var bottomNormal = this._bottom.normal;
|
||
if (this._bottom.distance + (bottomNormal.x * (bottomNormal.x < 0 ? minX : maxX)) + (bottomNormal.y * (bottomNormal.y < 0 ? minY : maxY)) + (bottomNormal.z * (bottomNormal.z < 0 ? minZ : maxZ)) < 0)
|
||
return false;
|
||
var topNormal = this._top.normal;
|
||
if (this._top.distance + (topNormal.x * (topNormal.x < 0 ? minX : maxX)) + (topNormal.y * (topNormal.y < 0 ? minY : maxY)) + (topNormal.z * (topNormal.z < 0 ? minZ : maxZ)) < 0)
|
||
return false;
|
||
var farNormal = this._far.normal;
|
||
if (this._far.distance + (farNormal.x * (farNormal.x < 0 ? minX : maxX)) + (farNormal.y * (farNormal.y < 0 ? minY : maxY)) + (farNormal.z * (farNormal.z < 0 ? minZ : maxZ)) < 0)
|
||
return false;
|
||
return true;
|
||
}
|
||
containsBoundBox(box) {
|
||
var p = BoundFrustum._tempV30, n = BoundFrustum._tempV31;
|
||
var boxMin = box.min;
|
||
var boxMax = box.max;
|
||
var result = ContainmentType.Contains;
|
||
for (var i = 0; i < 6; i++) {
|
||
var plane = this.getPlane(i);
|
||
var planeNor = plane.normal;
|
||
if (planeNor.x >= 0) {
|
||
p.x = boxMax.x;
|
||
n.x = boxMin.x;
|
||
}
|
||
else {
|
||
p.x = boxMin.x;
|
||
n.x = boxMax.x;
|
||
}
|
||
if (planeNor.y >= 0) {
|
||
p.y = boxMax.y;
|
||
n.y = boxMin.y;
|
||
}
|
||
else {
|
||
p.y = boxMin.y;
|
||
n.y = boxMax.y;
|
||
}
|
||
if (planeNor.z >= 0) {
|
||
p.z = boxMax.z;
|
||
n.z = boxMin.z;
|
||
}
|
||
else {
|
||
p.z = boxMin.z;
|
||
n.z = boxMax.z;
|
||
}
|
||
if (CollisionUtils.intersectsPlaneAndPoint(plane, p) === Plane.PlaneIntersectionType_Back)
|
||
return ContainmentType.Disjoint;
|
||
if (CollisionUtils.intersectsPlaneAndPoint(plane, n) === Plane.PlaneIntersectionType_Back)
|
||
result = ContainmentType.Intersects;
|
||
}
|
||
return result;
|
||
}
|
||
containsBoundSphere(sphere) {
|
||
var result = Plane.PlaneIntersectionType_Front;
|
||
var planeResult = Plane.PlaneIntersectionType_Front;
|
||
for (var i = 0; i < 6; i++) {
|
||
switch (i) {
|
||
case 0:
|
||
planeResult = CollisionUtils.intersectsPlaneAndSphere(this._near, sphere);
|
||
break;
|
||
case 1:
|
||
planeResult = CollisionUtils.intersectsPlaneAndSphere(this._far, sphere);
|
||
break;
|
||
case 2:
|
||
planeResult = CollisionUtils.intersectsPlaneAndSphere(this._left, sphere);
|
||
break;
|
||
case 3:
|
||
planeResult = CollisionUtils.intersectsPlaneAndSphere(this._right, sphere);
|
||
break;
|
||
case 4:
|
||
planeResult = CollisionUtils.intersectsPlaneAndSphere(this._top, sphere);
|
||
break;
|
||
case 5:
|
||
planeResult = CollisionUtils.intersectsPlaneAndSphere(this._bottom, sphere);
|
||
break;
|
||
}
|
||
switch (planeResult) {
|
||
case Plane.PlaneIntersectionType_Back:
|
||
return ContainmentType.Disjoint;
|
||
case Plane.PlaneIntersectionType_Intersecting:
|
||
result = Plane.PlaneIntersectionType_Intersecting;
|
||
break;
|
||
}
|
||
}
|
||
switch (result) {
|
||
case Plane.PlaneIntersectionType_Intersecting:
|
||
return ContainmentType.Intersects;
|
||
default:
|
||
return ContainmentType.Contains;
|
||
}
|
||
}
|
||
}
|
||
BoundFrustum._tempV30 = new Vector3();
|
||
BoundFrustum._tempV31 = new Vector3();
|
||
BoundFrustum._tempV32 = new Vector3();
|
||
BoundFrustum._tempV33 = new Vector3();
|
||
BoundFrustum._tempV34 = new Vector3();
|
||
BoundFrustum._tempV35 = new Vector3();
|
||
BoundFrustum._tempV36 = new Vector3();
|
||
|
||
class Viewport {
|
||
constructor(x, y, width, height) {
|
||
this.minDepth = 0.0;
|
||
this.maxDepth = 1.0;
|
||
this.x = x;
|
||
this.y = y;
|
||
this.width = width;
|
||
this.height = height;
|
||
}
|
||
project(source, matrix, out) {
|
||
Vector3.transformV3ToV4(source, matrix, out);
|
||
var x = out.x, y = out.y, z = out.z;
|
||
var w = out.w;
|
||
if (w !== 1.0) {
|
||
x = x / w;
|
||
y = y / w;
|
||
z = z / w;
|
||
}
|
||
out.x = (x + 1.0) * 0.5 * this.width + this.x;
|
||
out.y = (-y + 1.0) * 0.5 * this.height + this.y;
|
||
out.z = z * (this.maxDepth - this.minDepth) + this.minDepth;
|
||
}
|
||
unprojectFromMat(source, matrix, out) {
|
||
var matrixEleme = matrix.elements;
|
||
out.x = (((source.x - this.x) / this.width) * 2.0) - 1.0;
|
||
out.y = -((((source.y - this.y) / this.height) * 2.0) - 1.0);
|
||
out.z = (source.z - this.minDepth) / (this.maxDepth - this.minDepth);
|
||
var a = (((out.x * matrixEleme[3]) + (out.y * matrixEleme[7])) + (out.z * matrixEleme[11])) + matrixEleme[15];
|
||
Vector3.transformV3ToV3(out, matrix, out);
|
||
if (a !== 1.0) {
|
||
out.x = out.x / a;
|
||
out.y = out.y / a;
|
||
out.z = out.z / a;
|
||
}
|
||
}
|
||
unprojectFromWVP(source, projection, view, world, out) {
|
||
Matrix4x4.multiply(projection, view, Viewport._tempMatrix4x4);
|
||
(world) && (Matrix4x4.multiply(Viewport._tempMatrix4x4, world, Viewport._tempMatrix4x4));
|
||
Viewport._tempMatrix4x4.invert(Viewport._tempMatrix4x4);
|
||
this.unprojectFromMat(source, Viewport._tempMatrix4x4, out);
|
||
}
|
||
cloneTo(out) {
|
||
out.x = this.x;
|
||
out.y = this.y;
|
||
out.width = this.width;
|
||
out.height = this.height;
|
||
out.minDepth = this.minDepth;
|
||
out.maxDepth = this.maxDepth;
|
||
}
|
||
}
|
||
Viewport._tempMatrix4x4 = new Matrix4x4();
|
||
|
||
class Picker {
|
||
constructor() {
|
||
}
|
||
static calculateCursorRay(point, viewPort, projectionMatrix, viewMatrix, world, out) {
|
||
var x = point.x;
|
||
var y = point.y;
|
||
var nearSource = Picker._tempVector30;
|
||
var nerSourceE = nearSource;
|
||
nerSourceE.x = x;
|
||
nerSourceE.y = y;
|
||
nerSourceE.z = viewPort.minDepth;
|
||
var farSource = Picker._tempVector31;
|
||
var farSourceE = farSource;
|
||
farSourceE.x = x;
|
||
farSourceE.y = y;
|
||
farSourceE.z = viewPort.maxDepth;
|
||
var nearPoint = out.origin;
|
||
var farPoint = Picker._tempVector32;
|
||
viewPort.unprojectFromWVP(nearSource, projectionMatrix, viewMatrix, world, nearPoint);
|
||
viewPort.unprojectFromWVP(farSource, projectionMatrix, viewMatrix, world, farPoint);
|
||
var outDire = out.direction;
|
||
outDire.x = farPoint.x - nearPoint.x;
|
||
outDire.y = farPoint.y - nearPoint.y;
|
||
outDire.z = farPoint.z - nearPoint.z;
|
||
Vector3.normalize(out.direction, out.direction);
|
||
}
|
||
static rayIntersectsTriangle(ray, vertex1, vertex2, vertex3) {
|
||
var result;
|
||
var edge1 = Picker._tempVector30, edge2 = Picker._tempVector31;
|
||
Vector3.subtract(vertex2, vertex1, edge1);
|
||
Vector3.subtract(vertex3, vertex1, edge2);
|
||
var directionCrossEdge2 = Picker._tempVector32;
|
||
Vector3.cross(ray.direction, edge2, directionCrossEdge2);
|
||
var determinant;
|
||
determinant = Vector3.dot(edge1, directionCrossEdge2);
|
||
if (determinant > -Number.MIN_VALUE && determinant < Number.MIN_VALUE) {
|
||
result = Number.NaN;
|
||
return result;
|
||
}
|
||
var inverseDeterminant = 1.0 / determinant;
|
||
var distanceVector = Picker._tempVector33;
|
||
Vector3.subtract(ray.origin, vertex1, distanceVector);
|
||
var triangleU;
|
||
triangleU = Vector3.dot(distanceVector, directionCrossEdge2);
|
||
triangleU *= inverseDeterminant;
|
||
if (triangleU < 0 || triangleU > 1) {
|
||
result = Number.NaN;
|
||
return result;
|
||
}
|
||
var distanceCrossEdge1 = Picker._tempVector34;
|
||
Vector3.cross(distanceVector, edge1, distanceCrossEdge1);
|
||
var triangleV;
|
||
triangleV = Vector3.dot(ray.direction, distanceCrossEdge1);
|
||
triangleV *= inverseDeterminant;
|
||
if (triangleV < 0 || triangleU + triangleV > 1) {
|
||
result = Number.NaN;
|
||
return result;
|
||
}
|
||
var rayDistance;
|
||
rayDistance = Vector3.dot(edge2, distanceCrossEdge1);
|
||
rayDistance *= inverseDeterminant;
|
||
if (rayDistance < 0) {
|
||
result = Number.NaN;
|
||
return result;
|
||
}
|
||
result = rayDistance;
|
||
return result;
|
||
}
|
||
}
|
||
Picker._tempVector30 = new Vector3();
|
||
Picker._tempVector31 = new Vector3();
|
||
Picker._tempVector32 = new Vector3();
|
||
Picker._tempVector33 = new Vector3();
|
||
Picker._tempVector34 = new Vector3();
|
||
|
||
(function (IndexFormat) {
|
||
IndexFormat[IndexFormat["UInt8"] = 0] = "UInt8";
|
||
IndexFormat[IndexFormat["UInt16"] = 1] = "UInt16";
|
||
IndexFormat[IndexFormat["UInt32"] = 2] = "UInt32";
|
||
})(exports.IndexFormat || (exports.IndexFormat = {}));
|
||
|
||
class IndexBuffer3D extends Laya.Buffer {
|
||
constructor(indexType, indexCount, bufferUsage = 0x88E4, canRead = false) {
|
||
super();
|
||
this._indexType = indexType;
|
||
this._indexCount = indexCount;
|
||
this._bufferUsage = bufferUsage;
|
||
this._bufferType = Laya.LayaGL.instance.ELEMENT_ARRAY_BUFFER;
|
||
this._canRead = canRead;
|
||
switch (indexType) {
|
||
case exports.IndexFormat.UInt32:
|
||
this._indexTypeByteCount = 4;
|
||
break;
|
||
case exports.IndexFormat.UInt16:
|
||
this._indexTypeByteCount = 2;
|
||
break;
|
||
case exports.IndexFormat.UInt8:
|
||
this._indexTypeByteCount = 1;
|
||
break;
|
||
default:
|
||
throw new Error("unidentification index type.");
|
||
}
|
||
var byteLength = this._indexTypeByteCount * indexCount;
|
||
var curBufSta = Laya.BufferStateBase._curBindedBufferState;
|
||
this._byteLength = byteLength;
|
||
if (curBufSta) {
|
||
if (curBufSta._bindedIndexBuffer === this) {
|
||
Laya.LayaGL.instance.bufferData(this._bufferType, byteLength, this._bufferUsage);
|
||
}
|
||
else {
|
||
curBufSta.unBind();
|
||
this.bind();
|
||
Laya.LayaGL.instance.bufferData(this._bufferType, byteLength, this._bufferUsage);
|
||
curBufSta.bind();
|
||
}
|
||
}
|
||
else {
|
||
this.bind();
|
||
Laya.LayaGL.instance.bufferData(this._bufferType, byteLength, this._bufferUsage);
|
||
}
|
||
if (canRead) {
|
||
switch (indexType) {
|
||
case exports.IndexFormat.UInt32:
|
||
this._buffer = new Uint32Array(indexCount);
|
||
break;
|
||
case exports.IndexFormat.UInt16:
|
||
this._buffer = new Uint16Array(indexCount);
|
||
break;
|
||
case exports.IndexFormat.UInt8:
|
||
this._buffer = new Uint8Array(indexCount);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
get indexType() {
|
||
return this._indexType;
|
||
}
|
||
get indexTypeByteCount() {
|
||
return this._indexTypeByteCount;
|
||
}
|
||
get indexCount() {
|
||
return this._indexCount;
|
||
}
|
||
get canRead() {
|
||
return this._canRead;
|
||
}
|
||
_bindForVAO() {
|
||
if (Laya.BufferStateBase._curBindedBufferState) {
|
||
var gl = Laya.LayaGL.instance;
|
||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._glBuffer);
|
||
}
|
||
else {
|
||
throw "IndexBuffer3D: must bind current BufferState.";
|
||
}
|
||
}
|
||
bind() {
|
||
if (Laya.BufferStateBase._curBindedBufferState) {
|
||
throw "IndexBuffer3D: must unbind current BufferState.";
|
||
}
|
||
else {
|
||
if (Laya.Buffer._bindedIndexBuffer !== this._glBuffer) {
|
||
var gl = Laya.LayaGL.instance;
|
||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._glBuffer);
|
||
Laya.Buffer._bindedIndexBuffer = this._glBuffer;
|
||
return true;
|
||
}
|
||
else {
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
setData(data, bufferOffset = 0, dataStartIndex = 0, dataCount = 4294967295) {
|
||
var byteCount = this._indexTypeByteCount;
|
||
if (dataStartIndex !== 0 || dataCount !== 4294967295) {
|
||
switch (this._indexType) {
|
||
case exports.IndexFormat.UInt32:
|
||
data = new Uint32Array(data.buffer, dataStartIndex * byteCount, dataCount);
|
||
break;
|
||
case exports.IndexFormat.UInt16:
|
||
data = new Uint16Array(data.buffer, dataStartIndex * byteCount, dataCount);
|
||
break;
|
||
case exports.IndexFormat.UInt8:
|
||
data = new Uint8Array(data.buffer, dataStartIndex * byteCount, dataCount);
|
||
break;
|
||
}
|
||
}
|
||
var curBufSta = Laya.BufferStateBase._curBindedBufferState;
|
||
if (curBufSta) {
|
||
if (curBufSta._bindedIndexBuffer === this) {
|
||
Laya.LayaGL.instance.bufferSubData(this._bufferType, bufferOffset * byteCount, data);
|
||
}
|
||
else {
|
||
curBufSta.unBind();
|
||
this.bind();
|
||
Laya.LayaGL.instance.bufferSubData(this._bufferType, bufferOffset * byteCount, data);
|
||
curBufSta.bind();
|
||
}
|
||
}
|
||
else {
|
||
this.bind();
|
||
Laya.LayaGL.instance.bufferSubData(this._bufferType, bufferOffset * byteCount, data);
|
||
}
|
||
if (this._canRead) {
|
||
if (bufferOffset !== 0 || dataStartIndex !== 0 || dataCount !== 4294967295) {
|
||
var maxLength = this._buffer.length - bufferOffset;
|
||
if (dataCount > maxLength)
|
||
dataCount = maxLength;
|
||
for (var i = 0; i < dataCount; i++)
|
||
this._buffer[bufferOffset + i] = data[i];
|
||
}
|
||
else {
|
||
this._buffer = data;
|
||
}
|
||
}
|
||
}
|
||
getData() {
|
||
if (this._canRead)
|
||
return this._buffer;
|
||
else
|
||
throw new Error("Can't read data from VertexBuffer with only write flag!");
|
||
}
|
||
destroy() {
|
||
super.destroy();
|
||
this._buffer = null;
|
||
this._byteLength = 0;
|
||
this._indexCount = 0;
|
||
}
|
||
}
|
||
|
||
class SkyMesh {
|
||
constructor() {
|
||
}
|
||
_render(state) {
|
||
}
|
||
}
|
||
|
||
class SkyBox extends SkyMesh {
|
||
constructor() {
|
||
super();
|
||
var gl = Laya.LayaGL.instance;
|
||
var halfHeight = 1.0;
|
||
var halfWidth = 1.0;
|
||
var halfDepth = 1.0;
|
||
var vertices = new Float32Array([-halfDepth, halfHeight, -halfWidth, halfDepth, halfHeight, -halfWidth, halfDepth, halfHeight, halfWidth, -halfDepth, halfHeight, halfWidth,
|
||
-halfDepth, -halfHeight, -halfWidth, halfDepth, -halfHeight, -halfWidth, halfDepth, -halfHeight, halfWidth, -halfDepth, -halfHeight, halfWidth]);
|
||
var indices = new Uint8Array([
|
||
0, 1, 2, 2, 3, 0,
|
||
4, 7, 6, 6, 5, 4,
|
||
0, 3, 7, 7, 4, 0,
|
||
1, 5, 6, 6, 2, 1,
|
||
3, 2, 6, 6, 7, 3,
|
||
0, 4, 5, 5, 1, 0
|
||
]);
|
||
var verDec = VertexMesh.getVertexDeclaration("POSITION");
|
||
this._vertexBuffer = new VertexBuffer3D(verDec.vertexStride * 8, gl.STATIC_DRAW, false);
|
||
this._vertexBuffer.vertexDeclaration = verDec;
|
||
this._indexBuffer = new IndexBuffer3D(exports.IndexFormat.UInt8, 36, gl.STATIC_DRAW, false);
|
||
this._vertexBuffer.setData(vertices.buffer);
|
||
this._indexBuffer.setData(indices);
|
||
var bufferState = new BufferState();
|
||
bufferState.bind();
|
||
bufferState.applyVertexBuffer(this._vertexBuffer);
|
||
bufferState.applyIndexBuffer(this._indexBuffer);
|
||
bufferState.unBind();
|
||
this._bufferState = bufferState;
|
||
}
|
||
static __init__() {
|
||
SkyBox.instance = new SkyBox();
|
||
}
|
||
_render(state) {
|
||
var gl = Laya.LayaGL.instance;
|
||
gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_BYTE, 0);
|
||
Laya.Stat.trianglesFaces += 12;
|
||
Laya.Stat.renderBatches++;
|
||
}
|
||
}
|
||
|
||
class SkyRenderer {
|
||
constructor() {
|
||
this._mesh = SkyBox.instance;
|
||
}
|
||
get material() {
|
||
return this._material;
|
||
}
|
||
set material(value) {
|
||
if (this._material !== value) {
|
||
(this._material) && (this._material._removeReference());
|
||
(value) && (value._addReference());
|
||
this._material = value;
|
||
}
|
||
}
|
||
get mesh() {
|
||
return this._mesh;
|
||
}
|
||
set mesh(value) {
|
||
if (this._mesh !== value) {
|
||
this._mesh = value;
|
||
}
|
||
}
|
||
_isAvailable() {
|
||
return this._material && this._mesh ? true : false;
|
||
}
|
||
_render(context) {
|
||
if (this._material && this._mesh) {
|
||
var gl = Laya.LayaGL.instance;
|
||
var scene = context.scene;
|
||
var cameraShaderValue = context.cameraShaderValue;
|
||
var camera = context.camera;
|
||
var noteValue = ShaderData._SET_RUNTIME_VALUE_MODE_REFERENCE_;
|
||
Laya.ILaya.Render.supportWebGLPlusRendering && ShaderData.setRuntimeValueMode(false);
|
||
Laya.WebGLContext.setCullFace(gl, false);
|
||
Laya.WebGLContext.setDepthFunc(gl, gl.LEQUAL);
|
||
Laya.WebGLContext.setDepthMask(gl, false);
|
||
var comDef = SkyRenderer._compileDefine;
|
||
this._material._shaderValues._defineDatas.cloneTo(comDef);
|
||
var shader = context.shader = this._material._shader.getSubShaderAt(0)._passes[0].withCompile(comDef);
|
||
var switchShader = shader.bind();
|
||
var switchShaderLoop = (Laya.Stat.loopCount !== shader._uploadMark);
|
||
var uploadScene = (shader._uploadScene !== scene) || switchShaderLoop;
|
||
if (uploadScene || switchShader) {
|
||
shader.uploadUniforms(shader._sceneUniformParamsMap, scene._shaderValues, uploadScene);
|
||
shader._uploadScene = scene;
|
||
}
|
||
var uploadCamera = (shader._uploadCameraShaderValue !== cameraShaderValue) || switchShaderLoop;
|
||
if (uploadCamera || switchShader) {
|
||
var viewMatrix = SkyRenderer._tempMatrix0;
|
||
var projectionMatrix = SkyRenderer._tempMatrix1;
|
||
camera.viewMatrix.cloneTo(viewMatrix);
|
||
camera.projectionMatrix.cloneTo(projectionMatrix);
|
||
viewMatrix.setTranslationVector(Vector3._ZERO);
|
||
if (camera.orthographic)
|
||
Matrix4x4.createPerspective(camera.fieldOfView, camera.aspectRatio, camera.nearPlane, camera.farPlane, projectionMatrix);
|
||
var epsilon = 1e-6;
|
||
var yScale = 1.0 / Math.tan(3.1416 * camera.fieldOfView / 180 * 0.5);
|
||
projectionMatrix.elements[0] = yScale / camera.aspectRatio;
|
||
projectionMatrix.elements[5] = yScale;
|
||
projectionMatrix.elements[10] = epsilon - 1.0;
|
||
projectionMatrix.elements[11] = -1.0;
|
||
projectionMatrix.elements[14] = -0;
|
||
camera._applyViewProject(context, viewMatrix, projectionMatrix);
|
||
shader.uploadUniforms(shader._cameraUniformParamsMap, cameraShaderValue, uploadCamera);
|
||
shader._uploadCameraShaderValue = cameraShaderValue;
|
||
}
|
||
var uploadMaterial = (shader._uploadMaterial !== this._material) || switchShaderLoop;
|
||
if (uploadMaterial || switchShader) {
|
||
shader.uploadUniforms(shader._materialUniformParamsMap, this._material._shaderValues, uploadMaterial);
|
||
shader._uploadMaterial = this._material;
|
||
}
|
||
this._mesh._bufferState.bind();
|
||
this._mesh._render(context);
|
||
Laya.ILaya.Render.supportWebGLPlusRendering && ShaderData.setRuntimeValueMode(noteValue);
|
||
Laya.WebGLContext.setDepthFunc(gl, gl.LESS);
|
||
Laya.WebGLContext.setDepthMask(gl, true);
|
||
camera._applyViewProject(context, camera.viewMatrix, camera.projectionMatrix);
|
||
}
|
||
}
|
||
destroy() {
|
||
if (this._material) {
|
||
this._material._removeReference();
|
||
this._material = null;
|
||
}
|
||
}
|
||
}
|
||
SkyRenderer._tempMatrix0 = new Matrix4x4();
|
||
SkyRenderer._tempMatrix1 = new Matrix4x4();
|
||
SkyRenderer._compileDefine = new DefineDatas();
|
||
|
||
class BaseCamera extends Sprite3D {
|
||
constructor(nearPlane = 0.3, farPlane = 1000) {
|
||
super();
|
||
this._skyRenderer = new SkyRenderer();
|
||
this._forward = new Vector3();
|
||
this._up = new Vector3();
|
||
this.clearColor = new Vector4(100 / 255, 149 / 255, 237 / 255, 255 / 255);
|
||
this._shaderValues = new ShaderData(null);
|
||
this._fieldOfView = 60;
|
||
this._useUserProjectionMatrix = false;
|
||
this._orthographic = false;
|
||
this._orthographicVerticalSize = 10;
|
||
this.renderingOrder = 0;
|
||
this._nearPlane = nearPlane;
|
||
this._farPlane = farPlane;
|
||
this.cullingMask = 2147483647;
|
||
this.useOcclusionCulling = true;
|
||
}
|
||
get skyRenderer() {
|
||
return this._skyRenderer;
|
||
}
|
||
get fieldOfView() {
|
||
return this._fieldOfView;
|
||
}
|
||
set fieldOfView(value) {
|
||
this._fieldOfView = value;
|
||
this._calculateProjectionMatrix();
|
||
}
|
||
get nearPlane() {
|
||
return this._nearPlane;
|
||
}
|
||
set nearPlane(value) {
|
||
this._nearPlane = value;
|
||
this._calculateProjectionMatrix();
|
||
}
|
||
get farPlane() {
|
||
return this._farPlane;
|
||
}
|
||
set farPlane(vaule) {
|
||
this._farPlane = vaule;
|
||
this._calculateProjectionMatrix();
|
||
}
|
||
get orthographic() {
|
||
return this._orthographic;
|
||
}
|
||
set orthographic(vaule) {
|
||
this._orthographic = vaule;
|
||
this._calculateProjectionMatrix();
|
||
}
|
||
get orthographicVerticalSize() {
|
||
return this._orthographicVerticalSize;
|
||
}
|
||
set orthographicVerticalSize(vaule) {
|
||
this._orthographicVerticalSize = vaule;
|
||
this._calculateProjectionMatrix();
|
||
}
|
||
get renderingOrder() {
|
||
return this._renderingOrder;
|
||
}
|
||
set renderingOrder(value) {
|
||
this._renderingOrder = value;
|
||
this._sortCamerasByRenderingOrder();
|
||
}
|
||
_sortCamerasByRenderingOrder() {
|
||
if (this.displayedInStage) {
|
||
var cameraPool = this.scene._cameraPool;
|
||
var n = cameraPool.length - 1;
|
||
for (var i = 0; i < n; i++) {
|
||
if (cameraPool[i].renderingOrder > cameraPool[n].renderingOrder) {
|
||
var tempCamera = cameraPool[i];
|
||
cameraPool[i] = cameraPool[n];
|
||
cameraPool[n] = tempCamera;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
_calculateProjectionMatrix() {
|
||
}
|
||
_onScreenSizeChanged() {
|
||
this._calculateProjectionMatrix();
|
||
}
|
||
_prepareCameraToRender() {
|
||
var cameraSV = this._shaderValues;
|
||
this.transform.getForward(this._forward);
|
||
this.transform.getUp(this._up);
|
||
cameraSV.setVector3(BaseCamera.CAMERAPOS, this.transform.position);
|
||
cameraSV.setVector3(BaseCamera.CAMERADIRECTION, this._forward);
|
||
cameraSV.setVector3(BaseCamera.CAMERAUP, this._up);
|
||
}
|
||
render(shader = null, replacementTag = null) {
|
||
}
|
||
addLayer(layer) {
|
||
this.cullingMask |= Math.pow(2, layer);
|
||
}
|
||
removeLayer(layer) {
|
||
this.cullingMask &= ~Math.pow(2, layer);
|
||
}
|
||
addAllLayers() {
|
||
this.cullingMask = 2147483647;
|
||
}
|
||
removeAllLayers() {
|
||
this.cullingMask = 0;
|
||
}
|
||
resetProjectionMatrix() {
|
||
this._useUserProjectionMatrix = false;
|
||
this._calculateProjectionMatrix();
|
||
}
|
||
_onActive() {
|
||
this._scene._addCamera(this);
|
||
super._onActive();
|
||
}
|
||
_onInActive() {
|
||
this._scene._removeCamera(this);
|
||
super._onInActive();
|
||
}
|
||
_parse(data, spriteMap) {
|
||
super._parse(data, spriteMap);
|
||
this.orthographic = data.orthographic;
|
||
(data.orthographicVerticalSize !== undefined) && (this.orthographicVerticalSize = data.orthographicVerticalSize);
|
||
(data.fieldOfView !== undefined) && (this.fieldOfView = data.fieldOfView);
|
||
this.nearPlane = data.nearPlane;
|
||
this.farPlane = data.farPlane;
|
||
var color = data.clearColor;
|
||
this.clearColor = new Vector4(color[0], color[1], color[2], color[3]);
|
||
var skyboxMaterial = data.skyboxMaterial;
|
||
if (skyboxMaterial) {
|
||
this._skyRenderer.material = Laya.Loader.getRes(skyboxMaterial.path);
|
||
}
|
||
}
|
||
destroy(destroyChild = true) {
|
||
this._skyRenderer.destroy();
|
||
this._skyRenderer = null;
|
||
Laya.Laya.stage.off(Laya.Event.RESIZE, this, this._onScreenSizeChanged);
|
||
super.destroy(destroyChild);
|
||
}
|
||
_create() {
|
||
return new BaseCamera();
|
||
}
|
||
}
|
||
BaseCamera._tempMatrix4x40 = new Matrix4x4();
|
||
BaseCamera.CAMERAPOS = Shader3D.propertyNameToID("u_CameraPos");
|
||
BaseCamera.VIEWMATRIX = Shader3D.propertyNameToID("u_View");
|
||
BaseCamera.PROJECTMATRIX = Shader3D.propertyNameToID("u_Projection");
|
||
BaseCamera.VIEWPROJECTMATRIX = Shader3D.propertyNameToID("u_ViewProjection");
|
||
BaseCamera.CAMERADIRECTION = Shader3D.propertyNameToID("u_CameraDirection");
|
||
BaseCamera.CAMERAUP = Shader3D.propertyNameToID("u_CameraUp");
|
||
BaseCamera.VIEWPORT = Shader3D.propertyNameToID("u_Viewport");
|
||
BaseCamera.PROJECTION_PARAMS = Shader3D.propertyNameToID("u_ProjectionParams");
|
||
BaseCamera.DEPTHTEXTURE = Shader3D.propertyNameToID("u_CameraDepthTexture");
|
||
BaseCamera.DEPTHNORMALSTEXTURE = Shader3D.propertyNameToID("u_CameraDepthNormalsTexture");
|
||
BaseCamera.DEPTHZBUFFERPARAMS = Shader3D.propertyNameToID("u_ZBufferParams");
|
||
BaseCamera.SHADERDEFINE_DEPTH = Shader3D.getDefineByName("DEPTHMAP");
|
||
BaseCamera.SHADERDEFINE_DEPTHNORMALS = Shader3D.getDefineByName("DEPTHNORMALSMAP");
|
||
BaseCamera.RENDERINGTYPE_DEFERREDLIGHTING = "DEFERREDLIGHTING";
|
||
BaseCamera.RENDERINGTYPE_FORWARDRENDERING = "FORWARDRENDERING";
|
||
BaseCamera._invertYScaleMatrix = new Matrix4x4(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||
BaseCamera._invertYProjectionMatrix = new Matrix4x4();
|
||
BaseCamera._invertYProjectionViewMatrix = new Matrix4x4();
|
||
BaseCamera.CLEARFLAG_SOLIDCOLOR = 0;
|
||
BaseCamera.CLEARFLAG_SKY = 1;
|
||
BaseCamera.CLEARFLAG_DEPTHONLY = 2;
|
||
BaseCamera.CLEARFLAG_NONE = 3;
|
||
|
||
(function (ShadowMode) {
|
||
ShadowMode[ShadowMode["None"] = 0] = "None";
|
||
ShadowMode[ShadowMode["Hard"] = 1] = "Hard";
|
||
ShadowMode[ShadowMode["SoftLow"] = 2] = "SoftLow";
|
||
ShadowMode[ShadowMode["SoftHigh"] = 3] = "SoftHigh";
|
||
})(exports.ShadowMode || (exports.ShadowMode = {}));
|
||
|
||
class Scene3DShaderDeclaration {
|
||
}
|
||
|
||
(function (LightType) {
|
||
LightType[LightType["Directional"] = 0] = "Directional";
|
||
LightType[LightType["Spot"] = 1] = "Spot";
|
||
LightType[LightType["Point"] = 2] = "Point";
|
||
})(exports.LightType || (exports.LightType = {}));
|
||
class LightSprite extends Sprite3D {
|
||
constructor() {
|
||
super();
|
||
this._shadowMode = exports.ShadowMode.None;
|
||
this._isAlternate = false;
|
||
this._shadowResolution = 2048;
|
||
this._shadowDistance = 50.0;
|
||
this._shadowDepthBias = 1.0;
|
||
this._shadowNormalBias = 1.0;
|
||
this._shadowNearPlane = 0.1;
|
||
this._shadowStrength = 1.0;
|
||
this._lightWoldMatrix = new Matrix4x4();
|
||
this._intensity = 1.0;
|
||
this._intensityColor = new Vector3();
|
||
this.color = new Vector3(1.0, 1.0, 1.0);
|
||
this._lightmapBakedType = LightSprite.LIGHTMAPBAKEDTYPE_REALTIME;
|
||
}
|
||
get intensity() {
|
||
return this._intensity;
|
||
}
|
||
set intensity(value) {
|
||
this._intensity = value;
|
||
}
|
||
get shadowMode() {
|
||
return this._shadowMode;
|
||
}
|
||
set shadowMode(value) {
|
||
this._shadowMode = value;
|
||
}
|
||
get shadowDistance() {
|
||
return this._shadowDistance;
|
||
}
|
||
set shadowDistance(value) {
|
||
this._shadowDistance = value;
|
||
}
|
||
get shadowResolution() {
|
||
return this._shadowResolution;
|
||
}
|
||
set shadowResolution(value) {
|
||
this._shadowResolution = value;
|
||
}
|
||
get shadowDepthBias() {
|
||
return this._shadowDepthBias;
|
||
}
|
||
set shadowDepthBias(value) {
|
||
this._shadowDepthBias = value;
|
||
}
|
||
get shadowNormalBias() {
|
||
return this._shadowNormalBias;
|
||
}
|
||
set shadowNormalBias(value) {
|
||
this._shadowNormalBias = value;
|
||
}
|
||
get shadowStrength() {
|
||
return this._shadowStrength;
|
||
}
|
||
set shadowStrength(value) {
|
||
this._shadowStrength = value;
|
||
}
|
||
get shadowNearPlane() {
|
||
return this._shadowNearPlane;
|
||
}
|
||
set shadowNearPlane(value) {
|
||
this._shadowNearPlane = value;
|
||
}
|
||
get lightmapBakedType() {
|
||
return this._lightmapBakedType;
|
||
}
|
||
set lightmapBakedType(value) {
|
||
if (this._lightmapBakedType !== value) {
|
||
this._lightmapBakedType = value;
|
||
if (this.activeInHierarchy) {
|
||
if (value !== LightSprite.LIGHTMAPBAKEDTYPE_BAKED)
|
||
this._addToScene();
|
||
else
|
||
this._removeFromScene();
|
||
}
|
||
}
|
||
}
|
||
get lightWorldMatrix() {
|
||
var position = this.transform.position;
|
||
var quaterian = this.transform.rotation;
|
||
Matrix4x4.createAffineTransformation(position, quaterian, Vector3._ONE, this._lightWoldMatrix);
|
||
return this._lightWoldMatrix;
|
||
}
|
||
_parse(data, spriteMap) {
|
||
super._parse(data, spriteMap);
|
||
var colorData = data.color;
|
||
this.color.fromArray(colorData);
|
||
this.intensity = data.intensity;
|
||
this.lightmapBakedType = data.lightmapBakedType;
|
||
}
|
||
_cloneTo(destObject, rootSprite, dstSprite) {
|
||
super._cloneTo(destObject, rootSprite, dstSprite);
|
||
var spriteLight = destObject;
|
||
spriteLight.color = this.color.clone();
|
||
spriteLight.intensity = this.intensity;
|
||
spriteLight.lightmapBakedType = this.lightmapBakedType;
|
||
}
|
||
_addToScene() {
|
||
var scene = this._scene;
|
||
var maxLightCount = Config3D._config.maxLightCount;
|
||
if (scene._lightCount < maxLightCount) {
|
||
scene._lightCount++;
|
||
this._addToLightQueue();
|
||
this._isAlternate = false;
|
||
}
|
||
else {
|
||
scene._alternateLights.add(this);
|
||
this._isAlternate = true;
|
||
console.warn("LightSprite:light count has large than maxLightCount,the latest added light will be ignore.");
|
||
}
|
||
}
|
||
_removeFromScene() {
|
||
var scene = this._scene;
|
||
if (this._isAlternate) {
|
||
scene._alternateLights.remove(this);
|
||
}
|
||
else {
|
||
scene._lightCount--;
|
||
this._removeFromLightQueue();
|
||
if (scene._alternateLights._length > 0) {
|
||
var alternateLight = scene._alternateLights.shift();
|
||
alternateLight._addToLightQueue();
|
||
alternateLight._isAlternate = false;
|
||
scene._lightCount++;
|
||
}
|
||
}
|
||
}
|
||
_addToLightQueue() {
|
||
}
|
||
_removeFromLightQueue() {
|
||
}
|
||
_onActive() {
|
||
super._onActive();
|
||
(this.lightmapBakedType !== LightSprite.LIGHTMAPBAKEDTYPE_BAKED) && (this._addToScene());
|
||
}
|
||
_onInActive() {
|
||
super._onInActive();
|
||
(this.lightmapBakedType !== LightSprite.LIGHTMAPBAKEDTYPE_BAKED) && (this._removeFromScene());
|
||
}
|
||
_create() {
|
||
return new LightSprite();
|
||
}
|
||
get diffuseColor() {
|
||
console.log("LightSprite: discard property,please use color property instead.");
|
||
return this.color;
|
||
}
|
||
set diffuseColor(value) {
|
||
console.log("LightSprite: discard property,please use color property instead.");
|
||
this.color = value;
|
||
}
|
||
}
|
||
LightSprite.LIGHTMAPBAKEDTYPE_REALTIME = 0;
|
||
LightSprite.LIGHTMAPBAKEDTYPE_MIXED = 1;
|
||
LightSprite.LIGHTMAPBAKEDTYPE_BAKED = 2;
|
||
|
||
(function (ShadowCascadesMode) {
|
||
ShadowCascadesMode[ShadowCascadesMode["NoCascades"] = 0] = "NoCascades";
|
||
ShadowCascadesMode[ShadowCascadesMode["TwoCascades"] = 1] = "TwoCascades";
|
||
ShadowCascadesMode[ShadowCascadesMode["FourCascades"] = 2] = "FourCascades";
|
||
})(exports.ShadowCascadesMode || (exports.ShadowCascadesMode = {}));
|
||
|
||
var FrustumFace;
|
||
(function (FrustumFace) {
|
||
FrustumFace[FrustumFace["Near"] = 0] = "Near";
|
||
FrustumFace[FrustumFace["Far"] = 1] = "Far";
|
||
FrustumFace[FrustumFace["Left"] = 2] = "Left";
|
||
FrustumFace[FrustumFace["Right"] = 3] = "Right";
|
||
FrustumFace[FrustumFace["Bottom"] = 4] = "Bottom";
|
||
FrustumFace[FrustumFace["Top"] = 5] = "Top";
|
||
})(FrustumFace || (FrustumFace = {}));
|
||
class ShadowUtils {
|
||
static supportShadow() {
|
||
return Laya.LayaGL.layaGPUInstance._isWebGL2 || Laya.SystemUtils.supportRenderTextureFormat(Laya.RenderTextureFormat.Depth);
|
||
}
|
||
static init() {
|
||
if (Laya.LayaGL.layaGPUInstance._isWebGL2)
|
||
ShadowUtils._shadowTextureFormat = Laya.RenderTextureFormat.ShadowMap;
|
||
else
|
||
ShadowUtils._shadowTextureFormat = Laya.RenderTextureFormat.Depth;
|
||
}
|
||
static getTemporaryShadowTexture(witdh, height, depthFormat) {
|
||
var shadowMap = RenderTexture.createFromPool(witdh, height, ShadowUtils._shadowTextureFormat, depthFormat);
|
||
shadowMap.filterMode = Laya.FilterMode.Bilinear;
|
||
shadowMap.wrapModeU = Laya.WarpMode.Clamp;
|
||
shadowMap.wrapModeV = Laya.WarpMode.Clamp;
|
||
return shadowMap;
|
||
}
|
||
static getShadowBias(light, shadowProjectionMatrix, shadowResolution, out) {
|
||
var frustumSize;
|
||
if (light._lightType == exports.LightType.Directional) {
|
||
frustumSize = 2.0 / shadowProjectionMatrix.elements[0];
|
||
}
|
||
else if (light._lightType == exports.LightType.Spot) {
|
||
frustumSize = Math.tan(light.spotAngle * 0.5 * MathUtils3D.Deg2Rad) * light.range;
|
||
}
|
||
else {
|
||
console.warn("ShadowUtils:Only spot and directional shadow casters are supported now.");
|
||
frustumSize = 0.0;
|
||
}
|
||
var texelSize = frustumSize / shadowResolution;
|
||
var depthBias = -light._shadowDepthBias * texelSize;
|
||
var normalBias = -light._shadowNormalBias * texelSize;
|
||
if (light.shadowMode == exports.ShadowMode.SoftHigh) {
|
||
const kernelRadius = 2.5;
|
||
depthBias *= kernelRadius;
|
||
normalBias *= kernelRadius;
|
||
}
|
||
out.setValue(depthBias, normalBias, 0.0, 0.0);
|
||
}
|
||
static getCameraFrustumPlanes(cameraViewProjectMatrix, frustumPlanes) {
|
||
BoundFrustum.getPlanesFromMatrix(cameraViewProjectMatrix, frustumPlanes[FrustumFace.Near], frustumPlanes[FrustumFace.Far], frustumPlanes[FrustumFace.Left], frustumPlanes[FrustumFace.Right], frustumPlanes[FrustumFace.Top], frustumPlanes[FrustumFace.Bottom]);
|
||
}
|
||
static getFarWithRadius(radius, denominator) {
|
||
return Math.sqrt(radius * radius / denominator);
|
||
}
|
||
static getCascadesSplitDistance(twoSplitRatio, fourSplitRatio, cameraNear, shadowFar, fov, aspectRatio, cascadesMode, out) {
|
||
out[0] = cameraNear;
|
||
var range = shadowFar - cameraNear;
|
||
var tFov = Math.tan(fov * 0.5);
|
||
var denominator = 1.0 + tFov * tFov * (aspectRatio * aspectRatio + 1.0);
|
||
switch (cascadesMode) {
|
||
case exports.ShadowCascadesMode.NoCascades:
|
||
out[1] = ShadowUtils.getFarWithRadius(shadowFar, denominator);
|
||
break;
|
||
case exports.ShadowCascadesMode.TwoCascades:
|
||
out[1] = ShadowUtils.getFarWithRadius(cameraNear + range * twoSplitRatio, denominator);
|
||
out[2] = ShadowUtils.getFarWithRadius(shadowFar, denominator);
|
||
break;
|
||
case exports.ShadowCascadesMode.FourCascades:
|
||
out[1] = ShadowUtils.getFarWithRadius(cameraNear + range * fourSplitRatio.x, denominator);
|
||
out[2] = ShadowUtils.getFarWithRadius(cameraNear + range * fourSplitRatio.y, denominator);
|
||
out[3] = ShadowUtils.getFarWithRadius(cameraNear + range * fourSplitRatio.z, denominator);
|
||
out[4] = ShadowUtils.getFarWithRadius(shadowFar, denominator);
|
||
break;
|
||
}
|
||
}
|
||
static applySliceTransform(shadowSliceData, atlasWidth, atlasHeight, cascadeIndex, outShadowMatrices) {
|
||
var sliceE = ShadowUtils._tempMatrix0.elements;
|
||
var oneOverAtlasWidth = 1.0 / atlasWidth;
|
||
var oneOverAtlasHeight = 1.0 / atlasHeight;
|
||
sliceE[0] = shadowSliceData.resolution * oneOverAtlasWidth;
|
||
sliceE[5] = shadowSliceData.resolution * oneOverAtlasHeight;
|
||
sliceE[12] = shadowSliceData.offsetX * oneOverAtlasWidth;
|
||
sliceE[13] = shadowSliceData.offsetY * oneOverAtlasHeight;
|
||
sliceE[1] = sliceE[2] = sliceE[2] = sliceE[4] = sliceE[6] = sliceE[7] = sliceE[8] = sliceE[9] = sliceE[11] = sliceE[14] = 0;
|
||
sliceE[10] = sliceE[15] = 1;
|
||
var offset = cascadeIndex * 16;
|
||
Utils3D._mulMatrixArray(sliceE, outShadowMatrices, offset, outShadowMatrices, offset);
|
||
}
|
||
static getDirectionLightShadowCullPlanes(cameraFrustumPlanes, cascadeIndex, splitDistance, cameraNear, direction, shadowSliceData) {
|
||
var frustumCorners = ShadowUtils._frustumCorners;
|
||
var backPlaneFaces = ShadowUtils._backPlaneFaces;
|
||
var planeNeighbors = ShadowUtils._frustumPlaneNeighbors;
|
||
var twoPlaneCorners = ShadowUtils._frustumTwoPlaneCorners;
|
||
var edgePlanePoint2 = ShadowUtils._edgePlanePoint2;
|
||
var out = shadowSliceData.cullPlanes;
|
||
var near = cameraFrustumPlanes[FrustumFace.Near], far = cameraFrustumPlanes[FrustumFace.Far];
|
||
var left = cameraFrustumPlanes[FrustumFace.Left], right = cameraFrustumPlanes[FrustumFace.Right];
|
||
var bottom = cameraFrustumPlanes[FrustumFace.Bottom], top = cameraFrustumPlanes[FrustumFace.Top];
|
||
var splitNearDistance = splitDistance[cascadeIndex] - cameraNear;
|
||
var splitNear = ShadowUtils._adjustNearPlane;
|
||
var splitFar = ShadowUtils._adjustFarPlane;
|
||
near.normal.cloneTo(splitNear.normal);
|
||
far.normal.cloneTo(splitFar.normal);
|
||
splitNear.distance = near.distance - splitNearDistance;
|
||
splitFar.distance = Math.min(-near.distance + shadowSliceData.sphereCenterZ + shadowSliceData.splitBoundSphere.radius, far.distance);
|
||
BoundFrustum.get3PlaneInterPoint(splitNear, bottom, right, frustumCorners[exports.FrustumCorner.nearBottomRight]);
|
||
BoundFrustum.get3PlaneInterPoint(splitNear, top, right, frustumCorners[exports.FrustumCorner.nearTopRight]);
|
||
BoundFrustum.get3PlaneInterPoint(splitNear, top, left, frustumCorners[exports.FrustumCorner.nearTopLeft]);
|
||
BoundFrustum.get3PlaneInterPoint(splitNear, bottom, left, frustumCorners[exports.FrustumCorner.nearBottomLeft]);
|
||
BoundFrustum.get3PlaneInterPoint(splitFar, bottom, right, frustumCorners[exports.FrustumCorner.FarBottomRight]);
|
||
BoundFrustum.get3PlaneInterPoint(splitFar, top, right, frustumCorners[exports.FrustumCorner.FarTopRight]);
|
||
BoundFrustum.get3PlaneInterPoint(splitFar, top, left, frustumCorners[exports.FrustumCorner.FarTopLeft]);
|
||
BoundFrustum.get3PlaneInterPoint(splitFar, bottom, left, frustumCorners[exports.FrustumCorner.FarBottomLeft]);
|
||
var backIndex = 0;
|
||
for (var i = 0; i < 6; i++) {
|
||
var plane;
|
||
switch (i) {
|
||
case FrustumFace.Near:
|
||
plane = splitNear;
|
||
break;
|
||
case FrustumFace.Far:
|
||
plane = splitFar;
|
||
break;
|
||
default:
|
||
plane = cameraFrustumPlanes[i];
|
||
break;
|
||
}
|
||
if (Vector3.dot(plane.normal, direction) < 0.0) {
|
||
plane.cloneTo(out[backIndex]);
|
||
backPlaneFaces[backIndex] = i;
|
||
backIndex++;
|
||
}
|
||
}
|
||
var edgeIndex = backIndex;
|
||
for (var i = 0; i < backIndex; i++) {
|
||
var backFace = backPlaneFaces[i];
|
||
var neighborFaces = planeNeighbors[backFace];
|
||
for (var j = 0; j < 4; j++) {
|
||
var neighborFace = neighborFaces[j];
|
||
var notBackFace = true;
|
||
for (var k = 0; k < backIndex; k++)
|
||
if (neighborFace == backPlaneFaces[k]) {
|
||
notBackFace = false;
|
||
break;
|
||
}
|
||
if (notBackFace) {
|
||
var corners = twoPlaneCorners[backFace][neighborFace];
|
||
var point0 = frustumCorners[corners[0]];
|
||
var point1 = frustumCorners[corners[1]];
|
||
Vector3.add(point0, direction, edgePlanePoint2);
|
||
Plane.createPlaneBy3P(point0, point1, edgePlanePoint2, out[edgeIndex++]);
|
||
}
|
||
}
|
||
}
|
||
shadowSliceData.cullPlaneCount = edgeIndex;
|
||
}
|
||
static getBoundSphereByFrustum(near, far, fov, aspectRatio, cameraPos, forward, outBoundSphere) {
|
||
var centerZ;
|
||
var radius;
|
||
var k = Math.sqrt(1.0 + aspectRatio * aspectRatio) * Math.tan(fov / 2.0);
|
||
var k2 = k * k;
|
||
var farSNear = far - near;
|
||
var farANear = far + near;
|
||
if (k2 > farSNear / farANear) {
|
||
centerZ = far;
|
||
radius = far * k;
|
||
}
|
||
else {
|
||
centerZ = 0.5 * farANear * (1 + k2);
|
||
radius = 0.5 * Math.sqrt(farSNear * farSNear + 2.0 * (far * far + near * near) * k2 + farANear * farANear * k2 * k2);
|
||
}
|
||
var center = outBoundSphere.center;
|
||
outBoundSphere.radius = radius;
|
||
Vector3.scale(forward, centerZ, center);
|
||
Vector3.add(cameraPos, center, center);
|
||
return centerZ;
|
||
}
|
||
static getMaxTileResolutionInAtlas(atlasWidth, atlasHeight, tileCount) {
|
||
var resolution = Math.min(atlasWidth, atlasHeight);
|
||
var currentTileCount = Math.floor(atlasWidth / resolution) * Math.floor(atlasHeight / resolution);
|
||
while (currentTileCount < tileCount) {
|
||
resolution = Math.floor(resolution >> 1);
|
||
currentTileCount = Math.floor(atlasWidth / resolution) * Math.floor(atlasHeight / resolution);
|
||
}
|
||
return resolution;
|
||
}
|
||
static getDirectionalLightMatrices(lightUp, lightSide, lightForward, cascadeIndex, nearPlane, shadowResolution, shadowSliceData, shadowMatrices) {
|
||
var boundSphere = shadowSliceData.splitBoundSphere;
|
||
var center = boundSphere.center;
|
||
var radius = boundSphere.radius;
|
||
var halfShadowResolution = shadowResolution / 2;
|
||
var borderRadius = radius * halfShadowResolution / (halfShadowResolution - ShadowUtils.atlasBorderSize);
|
||
var borderDiam = borderRadius * 2.0;
|
||
var sizeUnit = shadowResolution / borderDiam;
|
||
var radiusUnit = borderDiam / shadowResolution;
|
||
var upLen = Math.ceil(Vector3.dot(center, lightUp) * sizeUnit) * radiusUnit;
|
||
var sideLen = Math.ceil(Vector3.dot(center, lightSide) * sizeUnit) * radiusUnit;
|
||
var forwardLen = Vector3.dot(center, lightForward);
|
||
center.x = lightUp.x * upLen + lightSide.x * sideLen + lightForward.x * forwardLen;
|
||
center.y = lightUp.y * upLen + lightSide.y * sideLen + lightForward.y * forwardLen;
|
||
center.z = lightUp.z * upLen + lightSide.z * sideLen + lightForward.z * forwardLen;
|
||
var origin = shadowSliceData.position;
|
||
var viewMatrix = shadowSliceData.viewMatrix;
|
||
var projectMatrix = shadowSliceData.projectionMatrix;
|
||
var viewProjectMatrix = shadowSliceData.viewProjectMatrix;
|
||
shadowSliceData.resolution = shadowResolution;
|
||
shadowSliceData.offsetX = (cascadeIndex % 2) * shadowResolution;
|
||
shadowSliceData.offsetY = Math.floor(cascadeIndex / 2) * shadowResolution;
|
||
Vector3.scale(lightForward, radius + nearPlane, origin);
|
||
Vector3.subtract(center, origin, origin);
|
||
Matrix4x4.createLookAt(origin, center, lightUp, viewMatrix);
|
||
Matrix4x4.createOrthoOffCenter(-borderRadius, borderRadius, -borderRadius, borderRadius, 0.0, radius * 2.0 + nearPlane, projectMatrix);
|
||
Matrix4x4.multiply(projectMatrix, viewMatrix, viewProjectMatrix);
|
||
Utils3D._mulMatrixArray(ShadowUtils._shadowMapScaleOffsetMatrix.elements, viewProjectMatrix.elements, 0, shadowMatrices, cascadeIndex * 16);
|
||
}
|
||
static getSpotLightShadowData(shadowSpotData, spotLight, resolution, shadowParams, shadowSpotMatrices, shadowMapSize) {
|
||
var out = shadowSpotData.position = spotLight.transform.position;
|
||
shadowSpotData.resolution = resolution;
|
||
shadowMapSize.setValue(1.0 / resolution, 1.0 / resolution, resolution, resolution);
|
||
shadowSpotData.offsetX = 0;
|
||
shadowSpotData.offsetY = 0;
|
||
var spotWorldMatrix = spotLight.lightWorldMatrix;
|
||
var viewMatrix = shadowSpotData.viewMatrix;
|
||
var projectMatrix = shadowSpotData.projectionMatrix;
|
||
var viewProjectMatrix = shadowSpotData.viewProjectMatrix;
|
||
var BoundFrustum = shadowSpotData.cameraCullInfo.boundFrustum;
|
||
spotWorldMatrix.invert(viewMatrix);
|
||
Matrix4x4.createPerspective(3.1416 * spotLight.spotAngle / 180.0, 1, 0.1, spotLight.range, projectMatrix);
|
||
shadowParams.y = spotLight.shadowStrength;
|
||
Matrix4x4.multiply(projectMatrix, viewMatrix, viewProjectMatrix);
|
||
BoundFrustum.matrix = viewProjectMatrix;
|
||
viewProjectMatrix.cloneTo(shadowSpotMatrices);
|
||
shadowSpotData.cameraCullInfo.position = out;
|
||
}
|
||
static prepareShadowReceiverShaderValues(light, shadowMapWidth, shadowMapHeight, shadowSliceDatas, cascadeCount, shadowMapSize, shadowParams, shadowMatrices, splitBoundSpheres) {
|
||
shadowMapSize.setValue(1.0 / shadowMapWidth, 1.0 / shadowMapHeight, shadowMapWidth, shadowMapHeight);
|
||
shadowParams.setValue(light._shadowStrength, 0.0, 0.0, 0.0);
|
||
if (cascadeCount > 1) {
|
||
const matrixFloatCount = 16;
|
||
for (var i = cascadeCount * matrixFloatCount, n = 4 * matrixFloatCount; i < n; i++)
|
||
shadowMatrices[i] = 0.0;
|
||
for (var i = 0; i < cascadeCount; i++) {
|
||
var boundSphere = shadowSliceDatas[i].splitBoundSphere;
|
||
var center = boundSphere.center;
|
||
var radius = boundSphere.radius;
|
||
var offset = i * 4;
|
||
splitBoundSpheres[offset] = center.x;
|
||
splitBoundSpheres[offset + 1] = center.y;
|
||
splitBoundSpheres[offset + 2] = center.z;
|
||
splitBoundSpheres[offset + 3] = radius * radius;
|
||
}
|
||
const sphereFloatCount = 4;
|
||
for (var i = cascadeCount * sphereFloatCount, n = 4 * sphereFloatCount; i < n; i++)
|
||
splitBoundSpheres[i] = 0.0;
|
||
}
|
||
}
|
||
}
|
||
ShadowUtils._tempMatrix0 = new Matrix4x4();
|
||
ShadowUtils._shadowMapScaleOffsetMatrix = new Matrix4x4(0.5, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.5, 0.5, 0.0, 1.0);
|
||
ShadowUtils._frustumCorners = [new Vector3(), new Vector3(), new Vector3(), new Vector3(), new Vector3(), new Vector3(), new Vector3(), new Vector3()];
|
||
ShadowUtils._adjustNearPlane = new Plane(new Vector3());
|
||
ShadowUtils._adjustFarPlane = new Plane(new Vector3());
|
||
ShadowUtils._backPlaneFaces = new Array(5);
|
||
ShadowUtils._edgePlanePoint2 = new Vector3();
|
||
ShadowUtils._frustumPlaneNeighbors = [
|
||
[FrustumFace.Left, FrustumFace.Right, FrustumFace.Top, FrustumFace.Bottom],
|
||
[FrustumFace.Left, FrustumFace.Right, FrustumFace.Top, FrustumFace.Bottom],
|
||
[FrustumFace.Near, FrustumFace.Far, FrustumFace.Top, FrustumFace.Bottom],
|
||
[FrustumFace.Near, FrustumFace.Far, FrustumFace.Top, FrustumFace.Bottom],
|
||
[FrustumFace.Near, FrustumFace.Far, FrustumFace.Left, FrustumFace.Right],
|
||
[FrustumFace.Near, FrustumFace.Far, FrustumFace.Left, FrustumFace.Right]
|
||
];
|
||
ShadowUtils._frustumTwoPlaneCorners = [
|
||
[[exports.FrustumCorner.unknown, exports.FrustumCorner.unknown], [exports.FrustumCorner.unknown, exports.FrustumCorner.unknown], [exports.FrustumCorner.nearBottomLeft, exports.FrustumCorner.nearTopLeft], [exports.FrustumCorner.nearTopRight, exports.FrustumCorner.nearBottomRight], [exports.FrustumCorner.nearBottomRight, exports.FrustumCorner.nearBottomLeft], [exports.FrustumCorner.nearTopLeft, exports.FrustumCorner.nearTopRight]],
|
||
[[exports.FrustumCorner.unknown, exports.FrustumCorner.unknown], [exports.FrustumCorner.unknown, exports.FrustumCorner.unknown], [exports.FrustumCorner.FarTopLeft, exports.FrustumCorner.FarBottomLeft], [exports.FrustumCorner.FarBottomRight, exports.FrustumCorner.FarTopRight], [exports.FrustumCorner.FarBottomLeft, exports.FrustumCorner.FarBottomRight], [exports.FrustumCorner.FarTopRight, exports.FrustumCorner.FarTopLeft]],
|
||
[[exports.FrustumCorner.nearTopLeft, exports.FrustumCorner.nearBottomLeft], [exports.FrustumCorner.FarBottomLeft, exports.FrustumCorner.FarTopLeft], [exports.FrustumCorner.unknown, exports.FrustumCorner.unknown], [exports.FrustumCorner.unknown, exports.FrustumCorner.unknown], [exports.FrustumCorner.nearBottomLeft, exports.FrustumCorner.FarBottomLeft], [exports.FrustumCorner.FarTopLeft, exports.FrustumCorner.nearTopLeft]],
|
||
[[exports.FrustumCorner.nearBottomRight, exports.FrustumCorner.nearTopRight], [exports.FrustumCorner.FarTopRight, exports.FrustumCorner.FarBottomRight], [exports.FrustumCorner.unknown, exports.FrustumCorner.unknown], [exports.FrustumCorner.unknown, exports.FrustumCorner.unknown], [exports.FrustumCorner.FarBottomRight, exports.FrustumCorner.nearBottomRight], [exports.FrustumCorner.nearTopRight, exports.FrustumCorner.FarTopRight]],
|
||
[[exports.FrustumCorner.nearBottomLeft, exports.FrustumCorner.nearBottomRight], [exports.FrustumCorner.FarBottomRight, exports.FrustumCorner.FarBottomLeft], [exports.FrustumCorner.FarBottomLeft, exports.FrustumCorner.nearBottomLeft], [exports.FrustumCorner.nearBottomRight, exports.FrustumCorner.FarBottomRight], [exports.FrustumCorner.unknown, exports.FrustumCorner.unknown], [exports.FrustumCorner.unknown, exports.FrustumCorner.unknown]],
|
||
[[exports.FrustumCorner.nearTopRight, exports.FrustumCorner.nearTopLeft], [exports.FrustumCorner.FarTopLeft, exports.FrustumCorner.FarTopRight], [exports.FrustumCorner.nearTopLeft, exports.FrustumCorner.FarTopLeft], [exports.FrustumCorner.FarTopRight, exports.FrustumCorner.nearTopRight], [exports.FrustumCorner.unknown, exports.FrustumCorner.unknown], [exports.FrustumCorner.unknown, exports.FrustumCorner.unknown]]
|
||
];
|
||
ShadowUtils.atlasBorderSize = 4.0;
|
||
|
||
(function (DepthTextureMode) {
|
||
DepthTextureMode[DepthTextureMode["None"] = 0] = "None";
|
||
DepthTextureMode[DepthTextureMode["Depth"] = 1] = "Depth";
|
||
DepthTextureMode[DepthTextureMode["DepthNormals"] = 2] = "DepthNormals";
|
||
DepthTextureMode[DepthTextureMode["MotionVectors"] = 4] = "MotionVectors";
|
||
})(exports.DepthTextureMode || (exports.DepthTextureMode = {}));
|
||
class DepthPass {
|
||
constructor() {
|
||
this._zBufferParams = new Vector4();
|
||
}
|
||
update(camera, depthType) {
|
||
this._viewPort = camera.viewport;
|
||
this._camera = camera;
|
||
switch (depthType) {
|
||
case exports.DepthTextureMode.Depth:
|
||
camera.depthTexture = this._depthTexture = RenderTexture.createFromPool(this._viewPort.width, this._viewPort.height, Laya.RenderTextureFormat.Depth, Laya.RenderTextureDepthFormat.DEPTH_16);
|
||
break;
|
||
case exports.DepthTextureMode.DepthNormals:
|
||
camera.depthNormalTexture = this._depthNormalsTexture = RenderTexture.createFromPool(this._viewPort.width, this._viewPort.height, Laya.RenderTextureFormat.R8G8B8A8, Laya.RenderTextureDepthFormat.DEPTH_16);
|
||
break;
|
||
case exports.DepthTextureMode.MotionVectors:
|
||
break;
|
||
default:
|
||
throw ("there is UnDefined type of DepthTextureMode");
|
||
}
|
||
}
|
||
render(context, depthType) {
|
||
var scene = context.scene;
|
||
switch (depthType) {
|
||
case exports.DepthTextureMode.Depth:
|
||
var shaderValues = scene._shaderValues;
|
||
context.pipelineMode = "ShadowCaster";
|
||
ShaderData.setRuntimeValueMode(false);
|
||
this._depthTexture._start();
|
||
shaderValues.setVector(DepthPass.DEFINE_SHADOW_BIAS, DepthPass.SHADOW_BIAS);
|
||
var gl = Laya.LayaGL.instance;
|
||
var offsetX = this._viewPort.x;
|
||
var offsetY = this._viewPort.y;
|
||
gl.enable(gl.SCISSOR_TEST);
|
||
gl.viewport(offsetX, offsetY, this._viewPort.width, this._viewPort.height);
|
||
gl.scissor(offsetX, offsetY, this._viewPort.width, this._viewPort.height);
|
||
gl.clear(gl.DEPTH_BUFFER_BIT);
|
||
scene._opaqueQueue._render(context);
|
||
this._depthTexture._end();
|
||
ShaderData.setRuntimeValueMode(true);
|
||
this._setupDepthModeShaderValue(depthType, this._camera);
|
||
context.pipelineMode = context.configPipeLineMode;
|
||
break;
|
||
case exports.DepthTextureMode.DepthNormals:
|
||
var shaderValues = scene._shaderValues;
|
||
context.pipelineMode = "DepthNormal";
|
||
ShaderData.setRuntimeValueMode(false);
|
||
this._depthNormalsTexture._start();
|
||
var gl = Laya.LayaGL.instance;
|
||
var offsetX = this._viewPort.x;
|
||
var offsetY = this._viewPort.y;
|
||
gl.enable(gl.SCISSOR_TEST);
|
||
gl.viewport(offsetX, offsetY, this._viewPort.width, this._viewPort.height);
|
||
gl.scissor(offsetX, offsetY, this._viewPort.width, this._viewPort.height);
|
||
gl.clearColor(0.5, 0.5, 1.0, 0.0);
|
||
gl.clear(gl.DEPTH_BUFFER_BIT | gl.COLOR_BUFFER_BIT);
|
||
scene._opaqueQueue._render(context);
|
||
this._depthNormalsTexture._end();
|
||
ShaderData.setRuntimeValueMode(true);
|
||
this._setupDepthModeShaderValue(depthType, this._camera);
|
||
context.pipelineMode = context.configPipeLineMode;
|
||
break;
|
||
case exports.DepthTextureMode.MotionVectors:
|
||
break;
|
||
default:
|
||
throw ("there is UnDefined type of DepthTextureMode");
|
||
}
|
||
}
|
||
_setupDepthModeShaderValue(depthType, camera) {
|
||
switch (depthType) {
|
||
case exports.DepthTextureMode.Depth:
|
||
var far = camera.farPlane;
|
||
var near = camera.nearPlane;
|
||
this._zBufferParams.setValue(1.0 - far / near, far / near, (near - far) / (near * far), 1 / near);
|
||
camera._shaderValues.setVector(DepthPass.DEFINE_SHADOW_BIAS, DepthPass.SHADOW_BIAS);
|
||
camera._shaderValues.setTexture(DepthPass.DEPTHTEXTURE, this._depthTexture);
|
||
camera._shaderValues.setVector(DepthPass.DEPTHZBUFFERPARAMS, this._zBufferParams);
|
||
break;
|
||
case exports.DepthTextureMode.DepthNormals:
|
||
camera._shaderValues.setTexture(DepthPass.DEPTHNORMALSTEXTURE, this._depthNormalsTexture);
|
||
break;
|
||
case exports.DepthTextureMode.MotionVectors:
|
||
break;
|
||
default:
|
||
throw ("there is UnDefined type of DepthTextureMode");
|
||
}
|
||
}
|
||
cleanUp() {
|
||
this._depthTexture && RenderTexture.recoverToPool(this._depthTexture);
|
||
this._depthNormalsTexture && RenderTexture.recoverToPool(this._depthNormalsTexture);
|
||
this._depthTexture = null;
|
||
this._depthNormalsTexture = null;
|
||
}
|
||
}
|
||
DepthPass.SHADOW_BIAS = new Vector4();
|
||
DepthPass.DEFINE_SHADOW_BIAS = Shader3D.propertyNameToID("u_ShadowBias");
|
||
DepthPass.DEPTHTEXTURE = Shader3D.propertyNameToID("u_CameraDepthTexture");
|
||
DepthPass.DEPTHNORMALSTEXTURE = Shader3D.propertyNameToID("u_CameraDepthNormalsTexture");
|
||
DepthPass.DEPTHZBUFFERPARAMS = Shader3D.propertyNameToID("u_ZBufferParams");
|
||
|
||
(function (CameraClearFlags) {
|
||
CameraClearFlags[CameraClearFlags["SolidColor"] = 0] = "SolidColor";
|
||
CameraClearFlags[CameraClearFlags["Sky"] = 1] = "Sky";
|
||
CameraClearFlags[CameraClearFlags["DepthOnly"] = 2] = "DepthOnly";
|
||
CameraClearFlags[CameraClearFlags["Nothing"] = 3] = "Nothing";
|
||
})(exports.CameraClearFlags || (exports.CameraClearFlags = {}));
|
||
(function (CameraEventFlags) {
|
||
CameraEventFlags[CameraEventFlags["BeforeForwardOpaque"] = 0] = "BeforeForwardOpaque";
|
||
CameraEventFlags[CameraEventFlags["BeforeSkyBox"] = 2] = "BeforeSkyBox";
|
||
CameraEventFlags[CameraEventFlags["BeforeTransparent"] = 4] = "BeforeTransparent";
|
||
CameraEventFlags[CameraEventFlags["BeforeImageEffect"] = 6] = "BeforeImageEffect";
|
||
CameraEventFlags[CameraEventFlags["AfterEveryThing"] = 8] = "AfterEveryThing";
|
||
})(exports.CameraEventFlags || (exports.CameraEventFlags = {}));
|
||
class Camera extends BaseCamera {
|
||
constructor(aspectRatio = 0, nearPlane = 0.3, farPlane = 1000) {
|
||
super(nearPlane, farPlane);
|
||
this._updateViewMatrix = true;
|
||
this._postProcess = null;
|
||
this._enableHDR = false;
|
||
this._viewportParams = new Vector4();
|
||
this._projectionParams = new Vector4();
|
||
this._needBuiltInRenderTexture = false;
|
||
this._offScreenRenderTexture = null;
|
||
this._internalRenderTexture = null;
|
||
this._internalCommandBuffer = new CommandBuffer();
|
||
this._cameraEventCommandBuffer = {};
|
||
this._clusterPlaneCacheFlag = new Vector2(-1, -1);
|
||
this._screenOffsetScale = new Vector4();
|
||
this.enableRender = true;
|
||
this.clearFlag = exports.CameraClearFlags.SolidColor;
|
||
this._viewMatrix = new Matrix4x4();
|
||
this._projectionMatrix = new Matrix4x4();
|
||
this._projectionViewMatrix = new Matrix4x4();
|
||
this._viewport = new Viewport(0, 0, 0, 0);
|
||
this._normalizedViewport = new Viewport(0, 0, 1, 1);
|
||
this._rayViewport = new Viewport(0, 0, 0, 0);
|
||
this._aspectRatio = aspectRatio;
|
||
this._boundFrustum = new BoundFrustum(new Matrix4x4());
|
||
this._calculateProjectionMatrix();
|
||
Laya.Laya.stage.on(Laya.Event.RESIZE, this, this._onScreenSizeChanged);
|
||
this.transform.on(Laya.Event.TRANSFORM_CHANGED, this, this._onTransformChanged);
|
||
}
|
||
static drawRenderTextureByScene(camera, scene, renderTexture, shader = null, replacementTag = null) {
|
||
if (camera.renderTarget != renderTexture) {
|
||
camera.renderTarget && RenderTexture.recoverToPool(camera.renderTarget);
|
||
camera.renderTarget = renderTexture;
|
||
}
|
||
var viewport = camera.viewport;
|
||
var needInternalRT = camera._needInternalRenderTexture();
|
||
var context = RenderContext3D._instance;
|
||
var scene = context.scene = scene;
|
||
context.pipelineMode = context.configPipeLineMode;
|
||
if (needInternalRT) {
|
||
camera._internalRenderTexture = RenderTexture.createFromPool(viewport.width, viewport.height, camera._getRenderTextureFormat(), Laya.RenderTextureDepthFormat.DEPTH_16);
|
||
camera._internalRenderTexture.filterMode = Laya.FilterMode.Bilinear;
|
||
}
|
||
else {
|
||
camera._internalRenderTexture = null;
|
||
}
|
||
var needShadowCasterPass = camera._renderShadowMap(scene, context);
|
||
camera._preRenderMainPass(context, scene, needInternalRT, viewport);
|
||
camera._renderMainPass(context, viewport, scene, shader, replacementTag, needInternalRT);
|
||
camera._aftRenderMainPass(needShadowCasterPass);
|
||
return camera.renderTarget;
|
||
}
|
||
get aspectRatio() {
|
||
if (this._aspectRatio === 0) {
|
||
var vp = this.viewport;
|
||
return vp.width / vp.height;
|
||
}
|
||
return this._aspectRatio;
|
||
}
|
||
set aspectRatio(value) {
|
||
if (value < 0)
|
||
throw new Error("Camera: the aspect ratio has to be a positive real number.");
|
||
this._aspectRatio = value;
|
||
this._calculateProjectionMatrix();
|
||
}
|
||
get viewport() {
|
||
if (this._offScreenRenderTexture)
|
||
this._calculationViewport(this._normalizedViewport, this._offScreenRenderTexture.width, this._offScreenRenderTexture.height);
|
||
else
|
||
this._calculationViewport(this._normalizedViewport, RenderContext3D.clientWidth, RenderContext3D.clientHeight);
|
||
return this._viewport;
|
||
}
|
||
set viewport(value) {
|
||
var width;
|
||
var height;
|
||
if (this._offScreenRenderTexture) {
|
||
width = this._offScreenRenderTexture.width;
|
||
height = this._offScreenRenderTexture.height;
|
||
}
|
||
else {
|
||
width = RenderContext3D.clientWidth;
|
||
height = RenderContext3D.clientHeight;
|
||
}
|
||
this._normalizedViewport.x = value.x / width;
|
||
this._normalizedViewport.y = value.y / height;
|
||
this._normalizedViewport.width = value.width / width;
|
||
this._normalizedViewport.height = value.height / height;
|
||
this._calculationViewport(this._normalizedViewport, width, height);
|
||
this._calculateProjectionMatrix();
|
||
}
|
||
get normalizedViewport() {
|
||
return this._normalizedViewport;
|
||
}
|
||
set normalizedViewport(value) {
|
||
var width;
|
||
var height;
|
||
if (this._offScreenRenderTexture) {
|
||
width = this._offScreenRenderTexture.width;
|
||
height = this._offScreenRenderTexture.height;
|
||
}
|
||
else {
|
||
width = RenderContext3D.clientWidth;
|
||
height = RenderContext3D.clientHeight;
|
||
}
|
||
if (this._normalizedViewport !== value)
|
||
value.cloneTo(this._normalizedViewport);
|
||
this._calculationViewport(value, width, height);
|
||
this._calculateProjectionMatrix();
|
||
}
|
||
get viewMatrix() {
|
||
if (this._updateViewMatrix) {
|
||
var scale = this.transform.getWorldLossyScale();
|
||
var scaleX = scale.x;
|
||
var scaleY = scale.y;
|
||
var scaleZ = scale.z;
|
||
var viewMatE = this._viewMatrix.elements;
|
||
this.transform.worldMatrix.cloneTo(this._viewMatrix);
|
||
viewMatE[0] /= scaleX;
|
||
viewMatE[1] /= scaleX;
|
||
viewMatE[2] /= scaleX;
|
||
viewMatE[4] /= scaleY;
|
||
viewMatE[5] /= scaleY;
|
||
viewMatE[6] /= scaleY;
|
||
viewMatE[8] /= scaleZ;
|
||
viewMatE[9] /= scaleZ;
|
||
viewMatE[10] /= scaleZ;
|
||
this._viewMatrix.invert(this._viewMatrix);
|
||
this._updateViewMatrix = false;
|
||
}
|
||
return this._viewMatrix;
|
||
}
|
||
get projectionMatrix() {
|
||
return this._projectionMatrix;
|
||
}
|
||
set projectionMatrix(value) {
|
||
this._projectionMatrix = value;
|
||
this._useUserProjectionMatrix = true;
|
||
}
|
||
get projectionViewMatrix() {
|
||
Matrix4x4.multiply(this.projectionMatrix, this.viewMatrix, this._projectionViewMatrix);
|
||
return this._projectionViewMatrix;
|
||
}
|
||
get boundFrustum() {
|
||
this._boundFrustum.matrix = this.projectionViewMatrix;
|
||
return this._boundFrustum;
|
||
}
|
||
get renderTarget() {
|
||
return this._offScreenRenderTexture;
|
||
}
|
||
set renderTarget(value) {
|
||
var lastValue = this._offScreenRenderTexture;
|
||
if (lastValue !== value) {
|
||
(lastValue) && (lastValue._isCameraTarget = false);
|
||
(value) && (value._isCameraTarget = true);
|
||
this._offScreenRenderTexture = value;
|
||
this._calculateProjectionMatrix();
|
||
}
|
||
}
|
||
get postProcess() {
|
||
return this._postProcess;
|
||
}
|
||
set postProcess(value) {
|
||
this._postProcess = value;
|
||
if (!value)
|
||
return;
|
||
value && value._init(this);
|
||
}
|
||
get enableHDR() {
|
||
return this._enableHDR;
|
||
}
|
||
set enableHDR(value) {
|
||
if (value && !Laya.SystemUtils.supportRenderTextureFormat(Laya.RenderTextureFormat.R16G16B16A16)) {
|
||
console.warn("Camera:can't enable HDR in this device.");
|
||
return;
|
||
}
|
||
this._enableHDR = value;
|
||
}
|
||
get enableBuiltInRenderTexture() {
|
||
return this._needBuiltInRenderTexture;
|
||
}
|
||
set enableBuiltInRenderTexture(value) {
|
||
this._needBuiltInRenderTexture = value;
|
||
}
|
||
get depthTextureMode() {
|
||
return this._depthTextureMode;
|
||
}
|
||
set depthTextureMode(value) {
|
||
this._depthTextureMode = value;
|
||
}
|
||
_calculationViewport(normalizedViewport, width, height) {
|
||
var lx = normalizedViewport.x * width;
|
||
var ly = normalizedViewport.y * height;
|
||
var rx = lx + Math.max(normalizedViewport.width * width, 0);
|
||
var ry = ly + Math.max(normalizedViewport.height * height, 0);
|
||
var ceilLeftX = Math.ceil(lx);
|
||
var ceilLeftY = Math.ceil(ly);
|
||
var floorRightX = Math.floor(rx);
|
||
var floorRightY = Math.floor(ry);
|
||
var pixelLeftX = ceilLeftX - lx >= 0.5 ? Math.floor(lx) : ceilLeftX;
|
||
var pixelLeftY = ceilLeftY - ly >= 0.5 ? Math.floor(ly) : ceilLeftY;
|
||
var pixelRightX = rx - floorRightX >= 0.5 ? Math.ceil(rx) : floorRightX;
|
||
var pixelRightY = ry - floorRightY >= 0.5 ? Math.ceil(ry) : floorRightY;
|
||
this._viewport.x = pixelLeftX;
|
||
this._viewport.y = pixelLeftY;
|
||
this._viewport.width = pixelRightX - pixelLeftX;
|
||
this._viewport.height = pixelRightY - pixelLeftY;
|
||
}
|
||
_calculateProjectionMatrix() {
|
||
if (!this._useUserProjectionMatrix) {
|
||
if (this._orthographic) {
|
||
var halfHeight = this.orthographicVerticalSize * 0.5;
|
||
var halfWidth = halfHeight * this.aspectRatio;
|
||
Matrix4x4.createOrthoOffCenter(-halfWidth, halfWidth, -halfHeight, halfHeight, this.nearPlane, this.farPlane, this._projectionMatrix);
|
||
}
|
||
else {
|
||
Matrix4x4.createPerspective(3.1416 * this.fieldOfView / 180.0, this.aspectRatio, this.nearPlane, this.farPlane, this._projectionMatrix);
|
||
}
|
||
}
|
||
}
|
||
_isLayerVisible(layer) {
|
||
return (Math.pow(2, layer) & this.cullingMask) != 0;
|
||
}
|
||
_onTransformChanged(flag) {
|
||
flag &= Transform3D.TRANSFORM_WORLDMATRIX;
|
||
(flag) && (this._updateViewMatrix = true);
|
||
}
|
||
_parse(data, spriteMap) {
|
||
super._parse(data, spriteMap);
|
||
var clearFlagData = data.clearFlag;
|
||
(clearFlagData !== undefined) && (this.clearFlag = clearFlagData);
|
||
var viewport = data.viewport;
|
||
this.normalizedViewport = new Viewport(viewport[0], viewport[1], viewport[2], viewport[3]);
|
||
var enableHDR = data.enableHDR;
|
||
(enableHDR !== undefined) && (this.enableHDR = enableHDR);
|
||
}
|
||
clone() {
|
||
let camera = super.clone();
|
||
camera.clearFlag = this.clearFlag;
|
||
camera.viewport = this.viewport;
|
||
this.normalizedViewport.cloneTo(camera.normalizedViewport);
|
||
camera.enableHDR = this.enableHDR;
|
||
camera.farPlane = this.farPlane;
|
||
camera.nearPlane = this.nearPlane;
|
||
camera.fieldOfView = this.fieldOfView;
|
||
camera.orthographic = this.orthographic;
|
||
return camera;
|
||
}
|
||
_getCanvasWidth() {
|
||
if (this._offScreenRenderTexture)
|
||
return this._offScreenRenderTexture.width;
|
||
else
|
||
return RenderContext3D.clientWidth;
|
||
}
|
||
_getCanvasHeight() {
|
||
if (this._offScreenRenderTexture)
|
||
return this._offScreenRenderTexture.height;
|
||
else
|
||
return RenderContext3D.clientHeight;
|
||
}
|
||
_getRenderTexture() {
|
||
return this._internalRenderTexture || this._offScreenRenderTexture;
|
||
}
|
||
_needInternalRenderTexture() {
|
||
return (this._postProcess && this._postProcess.enable) || this._enableHDR || this._needBuiltInRenderTexture ? true : false;
|
||
}
|
||
_getRenderTextureFormat() {
|
||
if (this._enableHDR)
|
||
return Laya.RenderTextureFormat.R16G16B16A16;
|
||
else
|
||
return Laya.RenderTextureFormat.R8G8B8;
|
||
}
|
||
_prepareCameraToRender() {
|
||
super._prepareCameraToRender();
|
||
var vp = this.viewport;
|
||
this._viewportParams.setValue(vp.x, vp.y, vp.width, vp.height);
|
||
this._projectionParams.setValue(this._nearPlane, this._farPlane, RenderContext3D._instance.invertY ? -1 : 1, 1 / this.farPlane);
|
||
this._shaderValues.setVector(BaseCamera.VIEWPORT, this._viewportParams);
|
||
this._shaderValues.setVector(BaseCamera.PROJECTION_PARAMS, this._projectionParams);
|
||
}
|
||
_applyViewProject(context, viewMat, proMat) {
|
||
var projectView;
|
||
var shaderData = this._shaderValues;
|
||
if (context.invertY) {
|
||
Matrix4x4.multiply(BaseCamera._invertYScaleMatrix, proMat, BaseCamera._invertYProjectionMatrix);
|
||
Matrix4x4.multiply(BaseCamera._invertYProjectionMatrix, viewMat, BaseCamera._invertYProjectionViewMatrix);
|
||
proMat = BaseCamera._invertYProjectionMatrix;
|
||
projectView = BaseCamera._invertYProjectionViewMatrix;
|
||
}
|
||
else {
|
||
Matrix4x4.multiply(proMat, viewMat, this._projectionViewMatrix);
|
||
projectView = this._projectionViewMatrix;
|
||
}
|
||
context.viewMatrix = viewMat;
|
||
context.projectionMatrix = proMat;
|
||
context.projectionViewMatrix = projectView;
|
||
shaderData.setMatrix4x4(BaseCamera.VIEWMATRIX, viewMat);
|
||
shaderData.setMatrix4x4(BaseCamera.PROJECTMATRIX, proMat);
|
||
shaderData.setMatrix4x4(BaseCamera.VIEWPROJECTMATRIX, projectView);
|
||
}
|
||
_updateClusterPlaneXY() {
|
||
var fieldOfView = this.fieldOfView;
|
||
var aspectRatio = this.aspectRatio;
|
||
if (this._clusterPlaneCacheFlag.x !== fieldOfView || this._clusterPlaneCacheFlag.y !== aspectRatio) {
|
||
var clusterCount = Config3D._config.lightClusterCount;
|
||
var xSlixe = clusterCount.x, ySlice = clusterCount.y;
|
||
var xCount = xSlixe + 1, yCount = ySlice + 1;
|
||
var xPlanes = this._clusterXPlanes, yPlanes = this._clusterYPlanes;
|
||
if (!xPlanes) {
|
||
xPlanes = this._clusterXPlanes = new Array(xCount);
|
||
yPlanes = this._clusterYPlanes = new Array(yCount);
|
||
for (var i = 0; i < xCount; i++)
|
||
xPlanes[i] = new Vector3();
|
||
for (var i = 0; i < yCount; i++)
|
||
yPlanes[i] = new Vector3();
|
||
}
|
||
var halfY = Math.tan((this.fieldOfView / 2) * Math.PI / 180);
|
||
var halfX = this.aspectRatio * halfY;
|
||
var yLengthPerCluster = 2 * halfY / xSlixe;
|
||
var xLengthPerCluster = 2 * halfX / ySlice;
|
||
for (var i = 0; i < xCount; i++) {
|
||
var angle = -halfX + xLengthPerCluster * i;
|
||
var bigHypot = Math.sqrt(1 + angle * angle);
|
||
var normX = 1 / bigHypot;
|
||
var xPlane = xPlanes[i];
|
||
xPlane.setValue(normX, 0, -angle * normX);
|
||
}
|
||
for (var i = 0; i < yCount; i++) {
|
||
var angle = halfY - yLengthPerCluster * i;
|
||
var bigHypot = Math.sqrt(1 + angle * angle);
|
||
var normY = -1 / bigHypot;
|
||
var yPlane = yPlanes[i];
|
||
yPlane.setValue(0, normY, -angle * normY);
|
||
}
|
||
this._clusterPlaneCacheFlag.x = fieldOfView;
|
||
this._clusterPlaneCacheFlag.y = aspectRatio;
|
||
}
|
||
}
|
||
_applyCommandBuffer(event, context) {
|
||
Laya.PerformancePlugin.begainSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D_RENDER_RENDERCOMMANDBUFFER);
|
||
var gl = Laya.LayaGL.instance;
|
||
var commandBufferArray = this._cameraEventCommandBuffer[event];
|
||
if (!commandBufferArray || commandBufferArray.length == 0)
|
||
return;
|
||
commandBufferArray.forEach(function (value) {
|
||
value._context = context;
|
||
value._apply();
|
||
});
|
||
(RenderTexture.currentActive) && (RenderTexture.currentActive._end());
|
||
if (this._internalRenderTexture || this._offScreenRenderTexture)
|
||
this._getRenderTexture()._start();
|
||
else {
|
||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||
}
|
||
gl.viewport(0, 0, context.viewport.width, context.viewport.height);
|
||
Laya.PerformancePlugin.endSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D_RENDER_RENDERCOMMANDBUFFER);
|
||
}
|
||
_renderShadowMap(scene, context) {
|
||
Laya.PerformancePlugin.begainSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D_RENDER_SHADOWMAP);
|
||
var shadowCasterPass;
|
||
var mainDirectLight = scene._mainDirectionLight;
|
||
var needShadowCasterPass = mainDirectLight && mainDirectLight.shadowMode !== exports.ShadowMode.None && ShadowUtils.supportShadow();
|
||
if (needShadowCasterPass) {
|
||
scene._shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_SPOT);
|
||
scene._shaderValues.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW);
|
||
shadowCasterPass = ILaya3D.Scene3D._shadowCasterPass;
|
||
shadowCasterPass.update(this, mainDirectLight, ILaya3D.ShadowLightType.DirectionLight);
|
||
shadowCasterPass.render(context, scene, ILaya3D.ShadowLightType.DirectionLight);
|
||
}
|
||
else {
|
||
scene._shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW);
|
||
}
|
||
var spotMainLight = scene._mainSpotLight;
|
||
var spotneedShadowCasterPass = spotMainLight && spotMainLight.shadowMode !== exports.ShadowMode.None && ShadowUtils.supportShadow();
|
||
if (spotneedShadowCasterPass) {
|
||
scene._shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW);
|
||
scene._shaderValues.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_SPOT);
|
||
shadowCasterPass = ILaya3D.Scene3D._shadowCasterPass;
|
||
shadowCasterPass.update(this, spotMainLight, ILaya3D.ShadowLightType.SpotLight);
|
||
shadowCasterPass.render(context, scene, ILaya3D.ShadowLightType.SpotLight);
|
||
}
|
||
else {
|
||
scene._shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_SPOT);
|
||
}
|
||
if (needShadowCasterPass)
|
||
scene._shaderValues.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW);
|
||
if (spotneedShadowCasterPass)
|
||
scene._shaderValues.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_SPOT);
|
||
Laya.PerformancePlugin.endSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D_RENDER_SHADOWMAP);
|
||
return needShadowCasterPass || spotneedShadowCasterPass;
|
||
}
|
||
_preRenderMainPass(context, scene, needInternalRT, viewport) {
|
||
context.camera = this;
|
||
context.cameraShaderValue = this._shaderValues;
|
||
Camera._updateMark++;
|
||
scene._preRenderScript();
|
||
var gl = Laya.LayaGL.instance;
|
||
if (needInternalRT && !this._offScreenRenderTexture && (this.clearFlag == exports.CameraClearFlags.DepthOnly || this.clearFlag == exports.CameraClearFlags.Nothing)) {
|
||
if (this._enableHDR) {
|
||
var grabTexture = RenderTexture.createFromPool(viewport.width, viewport.height, Laya.RenderTextureFormat.R8G8B8, Laya.RenderTextureDepthFormat.DEPTH_16);
|
||
grabTexture.filterMode = Laya.FilterMode.Bilinear;
|
||
Laya.WebGLContext.bindTexture(gl, gl.TEXTURE_2D, grabTexture._getSource());
|
||
gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, viewport.x, RenderContext3D.clientHeight - (viewport.y + viewport.height), viewport.width, viewport.height);
|
||
var blit = BlitScreenQuadCMD.create(grabTexture, this._internalRenderTexture);
|
||
blit.run();
|
||
blit.recover();
|
||
RenderTexture.recoverToPool(grabTexture);
|
||
}
|
||
else {
|
||
Laya.WebGLContext.bindTexture(gl, gl.TEXTURE_2D, this._internalRenderTexture._getSource());
|
||
gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, viewport.x, RenderContext3D.clientHeight - (viewport.y + viewport.height), viewport.width, viewport.height);
|
||
}
|
||
}
|
||
}
|
||
_renderMainPass(context, viewport, scene, shader, replacementTag, needInternalRT) {
|
||
var gl = Laya.LayaGL.instance;
|
||
var renderTex = this._getRenderTexture();
|
||
context.viewport = viewport;
|
||
this._prepareCameraToRender();
|
||
var multiLighting = Config3D._config._multiLighting;
|
||
Laya.PerformancePlugin.begainSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D_RENDER_CLUSTER);
|
||
(multiLighting) && (Cluster.instance.update(this, (scene)));
|
||
Laya.PerformancePlugin.endSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D_RENDER_CLUSTER);
|
||
Laya.PerformancePlugin.begainSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D_RENDER_CULLING);
|
||
scene._preCulling(context, this, shader, replacementTag);
|
||
Laya.PerformancePlugin.endSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D_RENDER_CULLING);
|
||
if (this.depthTextureMode != 0) {
|
||
this._applyViewProject(context, this.viewMatrix, this._projectionMatrix);
|
||
this._renderDepthMode(context);
|
||
}
|
||
(renderTex) && (renderTex._start());
|
||
this._applyViewProject(context, this.viewMatrix, this._projectionMatrix);
|
||
scene._clear(gl, context);
|
||
this._applyCommandBuffer(exports.CameraEventFlags.BeforeForwardOpaque, context);
|
||
Laya.PerformancePlugin.begainSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D_RENDER_RENDEROPAQUE);
|
||
scene._renderScene(context, ILaya3D.Scene3D.SCENERENDERFLAG_RENDERQPAQUE);
|
||
Laya.PerformancePlugin.endSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D_RENDER_RENDEROPAQUE);
|
||
this._applyCommandBuffer(exports.CameraEventFlags.BeforeSkyBox, context);
|
||
scene._renderScene(context, ILaya3D.Scene3D.SCENERENDERFLAG_SKYBOX);
|
||
this._applyCommandBuffer(exports.CameraEventFlags.BeforeTransparent, context);
|
||
Laya.PerformancePlugin.begainSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D_RENDER_RENDERTRANSPARENT);
|
||
scene._renderScene(context, ILaya3D.Scene3D.SCENERENDERFLAG_RENDERTRANSPARENT);
|
||
Laya.PerformancePlugin.endSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D_RENDER_RENDERTRANSPARENT);
|
||
scene._postRenderScript();
|
||
this._applyCommandBuffer(exports.CameraEventFlags.BeforeImageEffect, context);
|
||
(renderTex) && (renderTex._end());
|
||
if (needInternalRT) {
|
||
if (this._postProcess && this._postProcess.enable) {
|
||
Laya.PerformancePlugin.begainSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D_RENDER_POSTPROCESS);
|
||
this._postProcess._render();
|
||
this._postProcess._applyPostProcessCommandBuffers();
|
||
Laya.PerformancePlugin.endSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D_RENDER_POSTPROCESS);
|
||
}
|
||
else if (this._enableHDR || this._needBuiltInRenderTexture) {
|
||
var canvasWidth = this._getCanvasWidth(), canvasHeight = this._getCanvasHeight();
|
||
this._screenOffsetScale.setValue(viewport.x / canvasWidth, viewport.y / canvasHeight, viewport.width / canvasWidth, viewport.height / canvasHeight);
|
||
this._internalCommandBuffer._camera = this;
|
||
this._internalCommandBuffer.blitScreenQuad(this._internalRenderTexture, this._offScreenRenderTexture ? this._offScreenRenderTexture : null, this._screenOffsetScale, null, null, 0, true);
|
||
this._internalCommandBuffer._apply();
|
||
this._internalCommandBuffer.clear();
|
||
}
|
||
RenderTexture.recoverToPool(this._internalRenderTexture);
|
||
}
|
||
this._applyCommandBuffer(exports.CameraEventFlags.AfterEveryThing, context);
|
||
}
|
||
_renderDepthMode(context) {
|
||
Laya.PerformancePlugin.begainSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D_RENDER_RENDERDEPTHMDOE);
|
||
var cameraDepthMode = this._depthTextureMode;
|
||
if ((cameraDepthMode & exports.DepthTextureMode.Depth) != 0) {
|
||
Camera.depthPass.update(this, exports.DepthTextureMode.Depth);
|
||
Camera.depthPass.render(context, exports.DepthTextureMode.Depth);
|
||
}
|
||
if ((cameraDepthMode & exports.DepthTextureMode.DepthNormals) != 0) {
|
||
Camera.depthPass.update(this, exports.DepthTextureMode.DepthNormals);
|
||
Camera.depthPass.render(context, exports.DepthTextureMode.DepthNormals);
|
||
}
|
||
Laya.PerformancePlugin.endSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D_RENDER_RENDERDEPTHMDOE);
|
||
}
|
||
get depthTexture() {
|
||
return this._depthTexture;
|
||
}
|
||
set depthTexture(value) {
|
||
this._depthTexture = value;
|
||
}
|
||
get depthNormalTexture() {
|
||
return this._depthNormalsTexture;
|
||
}
|
||
set depthNormalTexture(value) {
|
||
this._depthNormalsTexture = value;
|
||
}
|
||
_aftRenderMainPass(needShadowPass) {
|
||
if (needShadowPass)
|
||
ILaya3D.Scene3D._shadowCasterPass.cleanUp();
|
||
Camera.depthPass.cleanUp();
|
||
}
|
||
render(shader = null, replacementTag = null) {
|
||
if (!this.activeInHierarchy)
|
||
return;
|
||
var viewport = this.viewport;
|
||
var needInternalRT = this._needInternalRenderTexture();
|
||
var context = RenderContext3D._instance;
|
||
var scene = context.scene = this._scene;
|
||
context.pipelineMode = context.configPipeLineMode;
|
||
if (needInternalRT) {
|
||
this._internalRenderTexture = RenderTexture.createFromPool(viewport.width, viewport.height, this._getRenderTextureFormat(), Laya.RenderTextureDepthFormat.DEPTH_16, 4);
|
||
this._internalRenderTexture.filterMode = Laya.FilterMode.Bilinear;
|
||
}
|
||
else {
|
||
this._internalRenderTexture = null;
|
||
}
|
||
var needShadowCasterPass = this._renderShadowMap(scene, context);
|
||
this._preRenderMainPass(context, scene, needInternalRT, viewport);
|
||
this._renderMainPass(context, viewport, scene, shader, replacementTag, needInternalRT);
|
||
this._aftRenderMainPass(needShadowCasterPass);
|
||
}
|
||
viewportPointToRay(point, out) {
|
||
this._rayViewport.x = this.viewport.x;
|
||
this._rayViewport.y = this.viewport.y;
|
||
this._rayViewport.width = Laya.Laya.stage._width;
|
||
this._rayViewport.height = Laya.Laya.stage._height;
|
||
Picker.calculateCursorRay(point, this._rayViewport, this._projectionMatrix, this.viewMatrix, null, out);
|
||
}
|
||
normalizedViewportPointToRay(point, out) {
|
||
var finalPoint = Camera._tempVector20;
|
||
var vp = this.viewport;
|
||
finalPoint.x = point.x * vp.width;
|
||
finalPoint.y = point.y * vp.height;
|
||
Picker.calculateCursorRay(finalPoint, this.viewport, this._projectionMatrix, this.viewMatrix, null, out);
|
||
}
|
||
worldToViewportPoint(position, out) {
|
||
Matrix4x4.multiply(this._projectionMatrix, this._viewMatrix, this._projectionViewMatrix);
|
||
this.viewport.project(position, this._projectionViewMatrix, out);
|
||
out.x = out.x / Laya.Laya.stage.clientScaleX;
|
||
out.y = out.y / Laya.Laya.stage.clientScaleY;
|
||
}
|
||
worldToNormalizedViewportPoint(position, out) {
|
||
Matrix4x4.multiply(this._projectionMatrix, this._viewMatrix, this._projectionViewMatrix);
|
||
this.normalizedViewport.project(position, this._projectionViewMatrix, out);
|
||
out.x = out.x / Laya.Laya.stage.clientScaleX;
|
||
out.y = out.y / Laya.Laya.stage.clientScaleY;
|
||
}
|
||
convertScreenCoordToOrthographicCoord(source, out) {
|
||
if (this._orthographic) {
|
||
var clientWidth = RenderContext3D.clientWidth;
|
||
var clientHeight = RenderContext3D.clientHeight;
|
||
var ratioX = this.orthographicVerticalSize * this.aspectRatio / clientWidth;
|
||
var ratioY = this.orthographicVerticalSize / clientHeight;
|
||
out.x = (-clientWidth / 2 + source.x * Laya.Laya.stage.clientScaleX) * ratioX;
|
||
out.y = (clientHeight / 2 - source.y * Laya.Laya.stage.clientScaleY) * ratioY;
|
||
out.z = (this.nearPlane - this.farPlane) * (source.z + 1) / 2 - this.nearPlane;
|
||
Vector3.transformCoordinate(out, this.transform.worldMatrix, out);
|
||
return true;
|
||
}
|
||
else {
|
||
return false;
|
||
}
|
||
}
|
||
destroy(destroyChild = true) {
|
||
this._offScreenRenderTexture = null;
|
||
this.transform.off(Laya.Event.TRANSFORM_CHANGED, this, this._onTransformChanged);
|
||
super.destroy(destroyChild);
|
||
}
|
||
addCommandBuffer(event, commandBuffer) {
|
||
var commandBufferArray = this._cameraEventCommandBuffer[event];
|
||
if (!commandBufferArray)
|
||
commandBufferArray = this._cameraEventCommandBuffer[event] = [];
|
||
if (commandBufferArray.indexOf(commandBuffer) < 0)
|
||
commandBufferArray.push(commandBuffer);
|
||
commandBuffer._camera = this;
|
||
}
|
||
removeCommandBuffer(event, commandBuffer) {
|
||
var commandBufferArray = this._cameraEventCommandBuffer[event];
|
||
if (commandBufferArray) {
|
||
var index = commandBufferArray.indexOf(commandBuffer);
|
||
if (index != -1)
|
||
commandBufferArray.splice(index, 1);
|
||
}
|
||
else
|
||
throw "Camera:unknown event.";
|
||
}
|
||
removeCommandBuffers(event) {
|
||
if (this._cameraEventCommandBuffer[event])
|
||
this._cameraEventCommandBuffer[event].length = 0;
|
||
}
|
||
_create() {
|
||
return new Camera();
|
||
}
|
||
}
|
||
Camera._tempVector20 = new Vector2();
|
||
Camera._updateMark = 0;
|
||
Camera.depthPass = new DepthPass();
|
||
|
||
class Input3D {
|
||
constructor() {
|
||
this._eventList = [];
|
||
this._mouseTouch = new MouseTouch();
|
||
this._touchPool = [];
|
||
this._touches = new SimpleSingletonList();
|
||
this._multiTouchEnabled = true;
|
||
this._pushEventList = ((e) => {
|
||
(e.cancelable) && (e.preventDefault());
|
||
this._eventList.push(e);
|
||
}).bind(this);
|
||
}
|
||
__init__(canvas, scene) {
|
||
this._scene = scene;
|
||
Physics3D._bullet && (Input3D._tempHitResult0 = new Laya.HitResult());
|
||
canvas.oncontextmenu = function (e) {
|
||
return false;
|
||
};
|
||
}
|
||
_onCanvasEvent(canvas) {
|
||
canvas.addEventListener('mousedown', this._pushEventList);
|
||
canvas.addEventListener('mouseup', this._pushEventList, true);
|
||
canvas.addEventListener('mousemove', this._pushEventList, true);
|
||
canvas.addEventListener("touchstart", this._pushEventList);
|
||
canvas.addEventListener("touchend", this._pushEventList, true);
|
||
canvas.addEventListener("touchmove", this._pushEventList, true);
|
||
canvas.addEventListener("touchcancel", this._pushEventList, true);
|
||
}
|
||
_offCanvasEvent(canvas) {
|
||
canvas.removeEventListener('mousedown', this._pushEventList);
|
||
canvas.removeEventListener('mouseup', this._pushEventList, true);
|
||
canvas.removeEventListener('mousemove', this._pushEventList, true);
|
||
canvas.removeEventListener("touchstart", this._pushEventList);
|
||
canvas.removeEventListener("touchend", this._pushEventList, true);
|
||
canvas.removeEventListener("touchmove", this._pushEventList, true);
|
||
canvas.removeEventListener("touchcancel", this._pushEventList, true);
|
||
this._eventList.length = 0;
|
||
this._touches.clear();
|
||
}
|
||
touchCount() {
|
||
return this._touches.length;
|
||
}
|
||
get multiTouchEnabled() {
|
||
return this._multiTouchEnabled;
|
||
}
|
||
set multiTouchEnabled(value) {
|
||
this._multiTouchEnabled = value;
|
||
}
|
||
_getTouch(touchID, type) {
|
||
var touch = this._touchPool[touchID];
|
||
if ((type == 0 && touch && touch._getIndexInList() != -1))
|
||
return null;
|
||
if (type == 1 && touch && (touch._getIndexInList() == -1))
|
||
return null;
|
||
if (!touch) {
|
||
touch = new Touch();
|
||
this._touchPool[touchID] = touch;
|
||
touch._identifier = touchID;
|
||
}
|
||
return touch;
|
||
}
|
||
_mouseTouchDown() {
|
||
var touch = this._mouseTouch;
|
||
var sprite = touch.sprite;
|
||
touch._pressedSprite = sprite;
|
||
touch._pressedLoopCount = Laya.Stat.loopCount;
|
||
if (sprite) {
|
||
var scripts = sprite._scripts;
|
||
if (scripts) {
|
||
for (var i = 0, n = scripts.length; i < n; i++)
|
||
scripts[i].onMouseDown();
|
||
}
|
||
}
|
||
}
|
||
_mouseTouchUp() {
|
||
var i, n;
|
||
var touch = this._mouseTouch;
|
||
var lastPressedSprite = touch._pressedSprite;
|
||
touch._pressedSprite = null;
|
||
touch._pressedLoopCount = -1;
|
||
var sprite = touch.sprite;
|
||
if (sprite) {
|
||
if (sprite === lastPressedSprite) {
|
||
var scripts = sprite._scripts;
|
||
if (scripts) {
|
||
for (i = 0, n = scripts.length; i < n; i++)
|
||
scripts[i].onMouseClick();
|
||
}
|
||
}
|
||
}
|
||
if (lastPressedSprite) {
|
||
var lastScripts = lastPressedSprite._scripts;
|
||
if (lastScripts) {
|
||
for (i = 0, n = lastScripts.length; i < n; i++)
|
||
lastScripts[i].onMouseUp();
|
||
}
|
||
}
|
||
}
|
||
_mouseTouchRayCast(cameras) {
|
||
if (!Physics3D._bullet && !Physics3D._cannon)
|
||
return;
|
||
var touchHitResult = Input3D._tempHitResult0;
|
||
var touchPos = Input3D._tempVector20;
|
||
var touchRay = Input3D._tempRay0;
|
||
touchHitResult.succeeded = false;
|
||
var x = this._mouseTouch.mousePositionX;
|
||
var y = this._mouseTouch.mousePositionY;
|
||
touchPos.x = x;
|
||
touchPos.y = y;
|
||
for (var i = cameras.length - 1; i >= 0; i--) {
|
||
var camera = cameras[i];
|
||
var viewport = camera.viewport;
|
||
if (touchPos.x >= viewport.x && touchPos.y >= viewport.y && touchPos.x <= viewport.width && touchPos.y <= viewport.height) {
|
||
camera.viewportPointToRay(touchPos, touchRay);
|
||
var sucess = this._scene._physicsSimulation.rayCast(touchRay, touchHitResult);
|
||
if (sucess || (camera.clearFlag === exports.CameraClearFlags.SolidColor || camera.clearFlag === exports.CameraClearFlags.Sky))
|
||
break;
|
||
}
|
||
}
|
||
var touch = this._mouseTouch;
|
||
var lastSprite = touch.sprite;
|
||
if (touchHitResult.succeeded) {
|
||
var touchSprite = touchHitResult.collider.owner;
|
||
touch.sprite = touchSprite;
|
||
var scripts = touchSprite._scripts;
|
||
if (lastSprite !== touchSprite) {
|
||
if (scripts) {
|
||
for (var j = 0, m = scripts.length; j < m; j++)
|
||
scripts[j].onMouseEnter();
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
touch.sprite = null;
|
||
}
|
||
if (lastSprite && (lastSprite !== touchSprite)) {
|
||
var outScripts = lastSprite._scripts;
|
||
if (outScripts) {
|
||
for (j = 0, m = outScripts.length; j < m; j++)
|
||
outScripts[j].onMouseOut();
|
||
}
|
||
}
|
||
}
|
||
_changeTouches(changedTouches, flag) {
|
||
var offsetX = 0, offsetY = 0;
|
||
var lastCount = this._touches.length;
|
||
for (var j = 0, m = changedTouches.length; j < m; j++) {
|
||
var nativeTouch = changedTouches[j];
|
||
var identifier = nativeTouch.identifier;
|
||
if (!this._multiTouchEnabled && this._touches.length !== 0 && flag == 0)
|
||
continue;
|
||
var touch = this._getTouch(identifier, flag);
|
||
if (flag == 1 && !touch)
|
||
continue;
|
||
var pos = this._touchPool[identifier]._position;
|
||
var mousePoint = Input3D._tempPoint;
|
||
mousePoint.setTo(nativeTouch.pageX, nativeTouch.pageY);
|
||
Laya.ILaya.stage._canvasTransform.invertTransformPoint(mousePoint);
|
||
var posX = mousePoint.x;
|
||
var posY = mousePoint.y;
|
||
switch (flag) {
|
||
case 0:
|
||
if (!!touch)
|
||
this._touches.add(touch);
|
||
offsetX += posX;
|
||
offsetY += posY;
|
||
break;
|
||
case 1:
|
||
if (!!touch)
|
||
this._touches.remove(touch);
|
||
offsetX -= posX;
|
||
offsetY -= posY;
|
||
break;
|
||
case 2:
|
||
offsetX = posX - pos.x;
|
||
offsetY = posY - pos.y;
|
||
break;
|
||
}
|
||
pos.x = posX;
|
||
pos.y = posY;
|
||
}
|
||
var touchCount = this._touches.length;
|
||
if (touchCount === 0) {
|
||
this._mouseTouch.mousePositionX = 0;
|
||
this._mouseTouch.mousePositionY = 0;
|
||
}
|
||
else {
|
||
this._mouseTouch.mousePositionX = (this._mouseTouch.mousePositionX * lastCount + offsetX) / touchCount;
|
||
this._mouseTouch.mousePositionY = (this._mouseTouch.mousePositionY * lastCount + offsetY) / touchCount;
|
||
}
|
||
}
|
||
_update() {
|
||
var enablePhysics = Physics3D._enablePhysics && !Laya.PhysicsSimulation.disableSimulation;
|
||
var i, n, j, m;
|
||
n = this._eventList.length;
|
||
var cameras = this._scene._cameraPool;
|
||
if (n > 0) {
|
||
var rayCast = false;
|
||
for (i = 0; i < n; i++) {
|
||
var e = this._eventList[i];
|
||
switch (e.type) {
|
||
case "mousedown":
|
||
(enablePhysics) && (this._mouseTouchDown());
|
||
break;
|
||
case "mouseup":
|
||
(enablePhysics) && (this._mouseTouchUp());
|
||
break;
|
||
case "mousemove":
|
||
var mousePoint = Input3D._tempPoint;
|
||
mousePoint.setTo(e.pageX, e.pageY);
|
||
Laya.ILaya.stage._canvasTransform.invertTransformPoint(mousePoint);
|
||
this._mouseTouch.mousePositionX = mousePoint.x;
|
||
this._mouseTouch.mousePositionY = mousePoint.y;
|
||
(enablePhysics) && (rayCast = true);
|
||
break;
|
||
case "touchstart":
|
||
var lastLength = this._touches.length;
|
||
this._changeTouches(e.changedTouches, 0);
|
||
if (enablePhysics) {
|
||
(!Config3D._config.isUseCannonPhysicsEngine) && (this._mouseTouchRayCast(cameras));
|
||
(lastLength === 0) && (this._mouseTouchDown());
|
||
}
|
||
break;
|
||
case "touchend":
|
||
case "touchcancel":
|
||
this._changeTouches(e.changedTouches, 1);
|
||
(enablePhysics && this._touches.length === 0) && (this._mouseTouchUp());
|
||
break;
|
||
case "touchmove":
|
||
this._changeTouches(e.changedTouches, 2);
|
||
(enablePhysics) && (rayCast = true);
|
||
break;
|
||
default:
|
||
throw "Input3D:unkonwn event type.";
|
||
}
|
||
}
|
||
(rayCast) && (!Config3D._config.isUseCannonPhysicsEngine) && (this._mouseTouchRayCast(cameras));
|
||
this._eventList.length = 0;
|
||
}
|
||
if (enablePhysics) {
|
||
var mouseTouch = this._mouseTouch;
|
||
var pressedSprite = mouseTouch._pressedSprite;
|
||
if (pressedSprite && (Laya.Stat.loopCount > mouseTouch._pressedLoopCount)) {
|
||
var pressedScripts = pressedSprite._scripts;
|
||
if (pressedScripts) {
|
||
for (j = 0, m = pressedScripts.length; j < m; j++)
|
||
pressedScripts[j].onMouseDrag();
|
||
}
|
||
}
|
||
var touchSprite = mouseTouch.sprite;
|
||
if (touchSprite) {
|
||
var scripts = touchSprite._scripts;
|
||
if (scripts) {
|
||
for (j = 0, m = scripts.length; j < m; j++)
|
||
scripts[j].onMouseOver();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
getTouch(index) {
|
||
if (index < this._touches.length) {
|
||
return this._touches.elements[index];
|
||
}
|
||
else {
|
||
return null;
|
||
}
|
||
}
|
||
}
|
||
Input3D._tempPoint = new Laya.Point();
|
||
Input3D._tempVector20 = new Vector2();
|
||
Input3D._tempRay0 = new Ray(new Vector3(), new Vector3());
|
||
|
||
class VertexPositionTexture0 {
|
||
constructor(position, textureCoordinate0) {
|
||
this._position = position;
|
||
this._textureCoordinate0 = textureCoordinate0;
|
||
}
|
||
static get vertexDeclaration() {
|
||
return VertexPositionTexture0._vertexDeclaration;
|
||
}
|
||
static __init__() {
|
||
VertexPositionTexture0._vertexDeclaration = new VertexDeclaration(20, [new VertexElement(0, VertexElementFormat.Vector3, VertexMesh.MESH_POSITION0),
|
||
new VertexElement(12, VertexElementFormat.Vector2, VertexMesh.MESH_TEXTURECOORDINATE0)]);
|
||
}
|
||
get position() {
|
||
return this._position;
|
||
}
|
||
get textureCoordinate0() {
|
||
return this._textureCoordinate0;
|
||
}
|
||
get vertexDeclaration() {
|
||
return VertexPositionTexture0._vertexDeclaration;
|
||
}
|
||
}
|
||
|
||
class SkyDome extends SkyMesh {
|
||
constructor(stacks = 48, slices = 48) {
|
||
super();
|
||
var gl = Laya.LayaGL.instance;
|
||
this._stacks = stacks;
|
||
this._slices = slices;
|
||
var vertexDeclaration = VertexPositionTexture0.vertexDeclaration;
|
||
var vertexFloatCount = vertexDeclaration.vertexStride / 4;
|
||
var numberVertices = (this._stacks + 1) * (this._slices + 1);
|
||
var numberIndices = (3 * this._stacks * (this._slices + 1)) * 2;
|
||
var vertices = new Float32Array(numberVertices * vertexFloatCount);
|
||
var indices = new Uint16Array(numberIndices);
|
||
var stackAngle = Math.PI / this._stacks;
|
||
var sliceAngle = (Math.PI * 2.0) / this._slices;
|
||
var vertexIndex = 0;
|
||
var vertexCount = 0;
|
||
var indexCount = 0;
|
||
for (var stack = 0; stack < (this._stacks + 1); stack++) {
|
||
var r = Math.sin(stack * stackAngle);
|
||
var y = Math.cos(stack * stackAngle);
|
||
for (var slice = 0; slice < (this._slices + 1); slice++) {
|
||
var x = r * Math.sin(slice * sliceAngle);
|
||
var z = r * Math.cos(slice * sliceAngle);
|
||
vertices[vertexCount + 0] = x * SkyDome._radius;
|
||
vertices[vertexCount + 1] = y * SkyDome._radius;
|
||
vertices[vertexCount + 2] = z * SkyDome._radius;
|
||
vertices[vertexCount + 3] = -(slice / this._slices) + 0.75;
|
||
vertices[vertexCount + 4] = stack / this._stacks;
|
||
vertexCount += vertexFloatCount;
|
||
if (stack != (this._stacks - 1)) {
|
||
indices[indexCount++] = vertexIndex + 1;
|
||
indices[indexCount++] = vertexIndex;
|
||
indices[indexCount++] = vertexIndex + (this._slices + 1);
|
||
indices[indexCount++] = vertexIndex + (this._slices + 1);
|
||
indices[indexCount++] = vertexIndex;
|
||
indices[indexCount++] = vertexIndex + (this._slices);
|
||
vertexIndex++;
|
||
}
|
||
}
|
||
}
|
||
this._vertexBuffer = new VertexBuffer3D(vertices.length * 4, gl.STATIC_DRAW, false);
|
||
this._vertexBuffer.vertexDeclaration = vertexDeclaration;
|
||
this._indexBuffer = new IndexBuffer3D(exports.IndexFormat.UInt16, indices.length, gl.STATIC_DRAW, false);
|
||
this._vertexBuffer.setData(vertices.buffer);
|
||
this._indexBuffer.setData(indices);
|
||
var bufferState = new BufferState();
|
||
bufferState.bind();
|
||
bufferState.applyVertexBuffer(this._vertexBuffer);
|
||
bufferState.applyIndexBuffer(this._indexBuffer);
|
||
bufferState.unBind();
|
||
this._bufferState = bufferState;
|
||
}
|
||
static __init__() {
|
||
SkyDome.instance = new SkyDome();
|
||
}
|
||
get stacks() {
|
||
return this._stacks;
|
||
}
|
||
get slices() {
|
||
return this._slices;
|
||
}
|
||
_render(state) {
|
||
var gl = Laya.LayaGL.instance;
|
||
var indexCount = this._indexBuffer.indexCount;
|
||
gl.drawElements(gl.TRIANGLES, indexCount, gl.UNSIGNED_SHORT, 0);
|
||
Laya.Stat.trianglesFaces += indexCount / 3;
|
||
Laya.Stat.renderBatches++;
|
||
}
|
||
}
|
||
SkyDome._radius = 1;
|
||
|
||
(function (TextureCubeFace) {
|
||
TextureCubeFace[TextureCubeFace["PositiveX"] = 0] = "PositiveX";
|
||
TextureCubeFace[TextureCubeFace["NegativeX"] = 1] = "NegativeX";
|
||
TextureCubeFace[TextureCubeFace["PositiveY"] = 2] = "PositiveY";
|
||
TextureCubeFace[TextureCubeFace["NegativeY"] = 3] = "NegativeY";
|
||
TextureCubeFace[TextureCubeFace["PositiveZ"] = 4] = "PositiveZ";
|
||
TextureCubeFace[TextureCubeFace["NegativeZ"] = 5] = "NegativeZ";
|
||
})(exports.TextureCubeFace || (exports.TextureCubeFace = {}));
|
||
class TextureCube extends Laya.BaseTexture {
|
||
constructor(size, format = Laya.TextureFormat.R8G8B8, mipmap = false) {
|
||
super(format, mipmap);
|
||
this._glTextureType = Laya.LayaGL.instance.TEXTURE_CUBE_MAP;
|
||
this._width = size;
|
||
this._height = size;
|
||
var gl = Laya.LayaGL.instance;
|
||
this._setWarpMode(gl.TEXTURE_WRAP_S, this._wrapModeU);
|
||
this._setWarpMode(gl.TEXTURE_WRAP_T, this._wrapModeV);
|
||
this._setFilterMode(this._filterMode);
|
||
this._setAnisotropy(this._anisoLevel);
|
||
if (this._mipmap) {
|
||
this._mipmapCount = Math.ceil(Math.log2(size)) + 1;
|
||
for (var i = 0; i < this._mipmapCount; i++)
|
||
this._setPixels([], i, Math.max(size >> i, 1), Math.max(size >> i, 1));
|
||
this._setGPUMemory(size * size * 4 * (1 + 1 / 3) * 6);
|
||
}
|
||
else {
|
||
this._mipmapCount = 1;
|
||
this._setGPUMemory(size * size * 4 * 6);
|
||
}
|
||
}
|
||
static get blackTexture() {
|
||
return TextureCube._blackTexture;
|
||
}
|
||
static get grayTexture() {
|
||
return TextureCube._grayTexture;
|
||
}
|
||
static __init__() {
|
||
var blackTexture = new TextureCube(1, Laya.TextureFormat.R8G8B8, false);
|
||
var grayTexture = new TextureCube(1, Laya.TextureFormat.R8G8B8, false);
|
||
var pixels = new Uint8Array(3);
|
||
pixels[0] = 0, pixels[1] = 0, pixels[2] = 0;
|
||
blackTexture.setSixSidePixels([pixels, pixels, pixels, pixels, pixels, pixels]);
|
||
blackTexture.lock = true;
|
||
pixels[0] = 128, pixels[1] = 128, pixels[2] = 128;
|
||
grayTexture.setSixSidePixels([pixels, pixels, pixels, pixels, pixels, pixels]);
|
||
grayTexture.lock = true;
|
||
TextureCube._grayTexture = grayTexture;
|
||
TextureCube._blackTexture = blackTexture;
|
||
}
|
||
static _parse(data, propertyParams = null, constructParams = null) {
|
||
var texture = constructParams ? new TextureCube(0, constructParams[0], constructParams[1]) : new TextureCube(0);
|
||
texture.setSixSideImageSources(data);
|
||
return texture;
|
||
}
|
||
static _parseBin(data, propertyParams = null, constructParams = null) {
|
||
var texture = constructParams ? new TextureCube(0, constructParams[0], constructParams[1]) : new TextureCube(0);
|
||
texture.setSixSideImageSources(data);
|
||
return texture;
|
||
}
|
||
static load(url, complete) {
|
||
var extension = (Laya.LoaderManager.createMap[Laya.Utils.getFilecompatibleExtension(url)]) ? Laya.Utils.getFilecompatibleExtension(url) : Laya.Utils.getFileExtension(url);
|
||
var type = Laya.LoaderManager.createMap[extension] ? Laya.LoaderManager.createMap[extension][0] : null;
|
||
Laya.ILaya.loader.create(url, complete, null, type);
|
||
}
|
||
get defaulteTexture() {
|
||
return TextureCube.grayTexture;
|
||
}
|
||
_setPixels(pixels, miplevel, width, height) {
|
||
var gl = Laya.LayaGL.instance;
|
||
var glFormat = this._getGLFormat();
|
||
Laya.WebGLContext.bindTexture(gl, this._glTextureType, this._glTexture);
|
||
if (this.format === Laya.TextureFormat.R8G8B8) {
|
||
gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, miplevel, glFormat, width, height, 0, glFormat, gl.UNSIGNED_BYTE, pixels[0]);
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, miplevel, glFormat, width, height, 0, glFormat, gl.UNSIGNED_BYTE, pixels[1]);
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, miplevel, glFormat, width, height, 0, glFormat, gl.UNSIGNED_BYTE, pixels[2]);
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, miplevel, glFormat, width, height, 0, glFormat, gl.UNSIGNED_BYTE, pixels[3]);
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, miplevel, glFormat, width, height, 0, glFormat, gl.UNSIGNED_BYTE, pixels[4]);
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, miplevel, glFormat, width, height, 0, glFormat, gl.UNSIGNED_BYTE, pixels[5]);
|
||
gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4);
|
||
}
|
||
else {
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, miplevel, glFormat, width, height, 0, glFormat, gl.UNSIGNED_BYTE, pixels[0]);
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, miplevel, glFormat, width, height, 0, glFormat, gl.UNSIGNED_BYTE, pixels[1]);
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, miplevel, glFormat, width, height, 0, glFormat, gl.UNSIGNED_BYTE, pixels[2]);
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, miplevel, glFormat, width, height, 0, glFormat, gl.UNSIGNED_BYTE, pixels[3]);
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, miplevel, glFormat, width, height, 0, glFormat, gl.UNSIGNED_BYTE, pixels[4]);
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, miplevel, glFormat, width, height, 0, glFormat, gl.UNSIGNED_BYTE, pixels[5]);
|
||
}
|
||
}
|
||
setSixSideImageSources(source, premultiplyAlpha = false) {
|
||
var width;
|
||
var height;
|
||
for (var i = 0; i < 6; i++) {
|
||
var img = source[i];
|
||
if (!img) {
|
||
console.log("TextureCube: image Source can't be null.");
|
||
return;
|
||
}
|
||
var nextWidth = img.width;
|
||
var nextHeight = img.height;
|
||
if (i > 0) {
|
||
if (width !== nextWidth) {
|
||
console.log("TextureCube: each side image's width and height must same.");
|
||
return;
|
||
}
|
||
}
|
||
width = nextWidth;
|
||
height = nextHeight;
|
||
if (width !== height) {
|
||
console.log("TextureCube: each side image's width and height must same.");
|
||
return;
|
||
}
|
||
}
|
||
this._width = width;
|
||
this._height = height;
|
||
var gl = Laya.LayaGL.instance;
|
||
Laya.WebGLContext.bindTexture(gl, this._glTextureType, this._glTexture);
|
||
var glFormat = this._getGLFormat();
|
||
if (!Laya.Render.isConchApp) {
|
||
(premultiplyAlpha) && (gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true));
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, glFormat, glFormat, gl.UNSIGNED_BYTE, source[0]);
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, glFormat, glFormat, gl.UNSIGNED_BYTE, source[1]);
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, glFormat, glFormat, gl.UNSIGNED_BYTE, source[2]);
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, glFormat, glFormat, gl.UNSIGNED_BYTE, source[3]);
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, glFormat, glFormat, gl.UNSIGNED_BYTE, source[4]);
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, glFormat, glFormat, gl.UNSIGNED_BYTE, source[5]);
|
||
(premultiplyAlpha) && (gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false));
|
||
}
|
||
else {
|
||
if (premultiplyAlpha == true) {
|
||
for (var j = 0; j < 6; j++)
|
||
source[j].setPremultiplyAlpha(premultiplyAlpha);
|
||
}
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source[0]);
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source[1]);
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source[2]);
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source[3]);
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source[4]);
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source[5]);
|
||
}
|
||
if (this._mipmap && this._isPot(width) && this._isPot(height)) {
|
||
gl.generateMipmap(this._glTextureType);
|
||
this._setGPUMemory(width * height * 4 * (1 + 1 / 3) * 6);
|
||
}
|
||
else {
|
||
this._setGPUMemory(width * height * 4 * 6);
|
||
}
|
||
this._setWarpMode(gl.TEXTURE_WRAP_S, this._wrapModeU);
|
||
this._setWarpMode(gl.TEXTURE_WRAP_T, this._wrapModeV);
|
||
this._setFilterMode(this._filterMode);
|
||
this._readyed = true;
|
||
this._activeResource();
|
||
}
|
||
setSixSidePixels(pixels, miplevel = 0) {
|
||
if (!pixels)
|
||
throw new Error("TextureCube:pixels can't be null.");
|
||
var width = Math.max(this._width >> miplevel, 1);
|
||
var height = Math.max(this._height >> miplevel, 1);
|
||
var pixelsCount = width * height * this._getFormatByteCount();
|
||
if (pixels[0].length < pixelsCount)
|
||
throw "TextureCube:pixels length should at least " + pixelsCount + ".";
|
||
this._setPixels(pixels, miplevel, width, height);
|
||
if (miplevel === 0) {
|
||
var gl = Laya.LayaGL.instance;
|
||
this._setWarpMode(gl.TEXTURE_WRAP_S, this._wrapModeU);
|
||
this._setWarpMode(gl.TEXTURE_WRAP_T, this._wrapModeV);
|
||
}
|
||
this._readyed = true;
|
||
this._activeResource();
|
||
}
|
||
setImageSource(face, imageSource, miplevel = 0) {
|
||
var width = this._width;
|
||
var height = this._height;
|
||
if (imageSource) {
|
||
if (width !== imageSource.width || height !== imageSource.height) {
|
||
console.log("TextureCube: imageSource's width and height must same.");
|
||
return;
|
||
}
|
||
}
|
||
var gl = Laya.LayaGL.instance;
|
||
Laya.WebGLContext.bindTexture(gl, this._glTextureType, this._glTexture);
|
||
var glFormat = this._getGLFormat();
|
||
switch (face) {
|
||
case exports.TextureCubeFace.NegativeX:
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, miplevel, glFormat, glFormat, gl.UNSIGNED_BYTE, imageSource);
|
||
break;
|
||
case exports.TextureCubeFace.PositiveX:
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, miplevel, glFormat, glFormat, gl.UNSIGNED_BYTE, imageSource);
|
||
break;
|
||
case exports.TextureCubeFace.NegativeY:
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, miplevel, glFormat, glFormat, gl.UNSIGNED_BYTE, imageSource);
|
||
break;
|
||
case exports.TextureCubeFace.PositiveY:
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, miplevel, glFormat, glFormat, gl.UNSIGNED_BYTE, imageSource);
|
||
break;
|
||
case exports.TextureCubeFace.NegativeZ:
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, miplevel, glFormat, glFormat, gl.UNSIGNED_BYTE, imageSource);
|
||
break;
|
||
case exports.TextureCubeFace.PositiveZ:
|
||
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, miplevel, glFormat, glFormat, gl.UNSIGNED_BYTE, imageSource);
|
||
break;
|
||
}
|
||
if (this._mipmap && this._isPot(width) && this._isPot(height)) {
|
||
gl.generateMipmap(this._glTextureType);
|
||
this._setGPUMemory(width * height * 4 * (1 + 1 / 3) * 6);
|
||
}
|
||
else {
|
||
this._setGPUMemory(width * height * 4 * 6);
|
||
}
|
||
this._setWarpMode(gl.TEXTURE_WRAP_S, this._wrapModeU);
|
||
this._setWarpMode(gl.TEXTURE_WRAP_T, this._wrapModeV);
|
||
this._setFilterMode(this._filterMode);
|
||
this._readyed = true;
|
||
}
|
||
}
|
||
TextureCube.TEXTURECUBE = "TEXTURECUBE";
|
||
TextureCube.TEXTURECUBEBIN = "TEXTURECUBEBIN";
|
||
|
||
class LightQueue {
|
||
constructor() {
|
||
this._length = 0;
|
||
this._elements = [];
|
||
}
|
||
add(light) {
|
||
if (this._length === this._elements.length)
|
||
this._elements.push(light);
|
||
else
|
||
this._elements[this._length] = light;
|
||
this._length++;
|
||
}
|
||
remove(light) {
|
||
var index = this._elements.indexOf(light);
|
||
this._length--;
|
||
if (index !== this._length) {
|
||
var end = this._elements[this._length];
|
||
this._elements[index] = end;
|
||
}
|
||
}
|
||
shift() {
|
||
this._length--;
|
||
return this._elements.shift();
|
||
}
|
||
getBrightestLight() {
|
||
var maxIntIndex;
|
||
var maxIntensity = -1;
|
||
var elements = this._elements;
|
||
for (var i = 0; i < this._length; i++) {
|
||
var intensity = elements[i]._intensity;
|
||
if (maxIntensity < intensity) {
|
||
maxIntensity = intensity;
|
||
maxIntIndex = i;
|
||
}
|
||
}
|
||
return maxIntIndex;
|
||
}
|
||
normalLightOrdering(brightestIndex) {
|
||
var firstLight = this._elements[0];
|
||
this._elements[0] = this._elements[brightestIndex];
|
||
this._elements[brightestIndex] = firstLight;
|
||
}
|
||
}
|
||
class AlternateLightQueue extends LightQueue {
|
||
remove(light) {
|
||
var index = this._elements.indexOf(light);
|
||
this._elements.splice(index, 1);
|
||
this._length--;
|
||
}
|
||
}
|
||
|
||
class PixelLineMaterial extends Material {
|
||
constructor() {
|
||
super();
|
||
this.setShaderName("LineShader");
|
||
this._shaderValues.setVector(PixelLineMaterial.COLOR, new Vector4(1.0, 1.0, 1.0, 1.0));
|
||
}
|
||
static __initDefine__() {
|
||
}
|
||
get color() {
|
||
return this._shaderValues.getVector(PixelLineMaterial.COLOR);
|
||
}
|
||
set color(value) {
|
||
this._shaderValues.setVector(PixelLineMaterial.COLOR, value);
|
||
}
|
||
clone() {
|
||
var dest = new PixelLineMaterial();
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
}
|
||
PixelLineMaterial.COLOR = Shader3D.propertyNameToID("u_Color");
|
||
|
||
class BoundBox {
|
||
constructor(min, max) {
|
||
this.min = min;
|
||
this.max = max;
|
||
}
|
||
_rotateExtents(extents, rotation, out) {
|
||
var extentsX = extents.x;
|
||
var extentsY = extents.y;
|
||
var extentsZ = extents.z;
|
||
var matElements = rotation.elements;
|
||
out.x = Math.abs(matElements[0] * extentsX) + Math.abs(matElements[4] * extentsY) + Math.abs(matElements[8] * extentsZ);
|
||
out.y = Math.abs(matElements[1] * extentsX) + Math.abs(matElements[5] * extentsY) + Math.abs(matElements[9] * extentsZ);
|
||
out.z = Math.abs(matElements[2] * extentsX) + Math.abs(matElements[6] * extentsY) + Math.abs(matElements[10] * extentsZ);
|
||
}
|
||
getCorners(corners) {
|
||
corners.length = 8;
|
||
var minX = this.min.x;
|
||
var minY = this.min.y;
|
||
var minZ = this.min.z;
|
||
var maxX = this.max.x;
|
||
var maxY = this.max.y;
|
||
var maxZ = this.max.z;
|
||
corners[0] = new Vector3(minX, maxY, maxZ);
|
||
corners[1] = new Vector3(maxX, maxY, maxZ);
|
||
corners[2] = new Vector3(maxX, minY, maxZ);
|
||
corners[3] = new Vector3(minX, minY, maxZ);
|
||
corners[4] = new Vector3(minX, maxY, minZ);
|
||
corners[5] = new Vector3(maxX, maxY, minZ);
|
||
corners[6] = new Vector3(maxX, minY, minZ);
|
||
corners[7] = new Vector3(minX, minY, minZ);
|
||
}
|
||
getCenter(out) {
|
||
Vector3.add(this.min, this.max, out);
|
||
Vector3.scale(out, 0.5, out);
|
||
}
|
||
getExtent(out) {
|
||
Vector3.subtract(this.max, this.min, out);
|
||
Vector3.scale(out, 0.5, out);
|
||
}
|
||
setCenterAndExtent(center, extent) {
|
||
Vector3.subtract(center, extent, this.min);
|
||
Vector3.add(center, extent, this.max);
|
||
}
|
||
tranform(matrix, out) {
|
||
var center = BoundBox._tempVector30;
|
||
var extent = BoundBox._tempVector31;
|
||
this.getCenter(center);
|
||
this.getExtent(extent);
|
||
Vector3.transformCoordinate(center, matrix, center);
|
||
this._rotateExtents(extent, matrix, extent);
|
||
out.setCenterAndExtent(center, extent);
|
||
}
|
||
toDefault() {
|
||
this.min.toDefault();
|
||
this.max.toDefault();
|
||
}
|
||
static createfromPoints(points, out) {
|
||
if (points == null)
|
||
throw new Error("points");
|
||
var min = out.min;
|
||
var max = out.max;
|
||
min.x = Number.MAX_VALUE;
|
||
min.y = Number.MAX_VALUE;
|
||
min.z = Number.MAX_VALUE;
|
||
max.x = -Number.MAX_VALUE;
|
||
max.y = -Number.MAX_VALUE;
|
||
max.z = -Number.MAX_VALUE;
|
||
for (var i = 0, n = points.length; i < n; ++i) {
|
||
Vector3.min(min, points[i], min);
|
||
Vector3.max(max, points[i], max);
|
||
}
|
||
}
|
||
static merge(box1, box2, out) {
|
||
Vector3.min(box1.min, box2.min, out.min);
|
||
Vector3.max(box1.max, box2.max, out.max);
|
||
}
|
||
cloneTo(destObject) {
|
||
var dest = destObject;
|
||
this.min.cloneTo(dest.min);
|
||
this.max.cloneTo(dest.max);
|
||
}
|
||
clone() {
|
||
var dest = new BoundBox(new Vector3(), new Vector3());
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
}
|
||
BoundBox._tempVector30 = new Vector3();
|
||
BoundBox._tempVector31 = new Vector3();
|
||
|
||
class Bounds {
|
||
constructor(min, max) {
|
||
this._updateFlag = 0;
|
||
this._center = new Vector3();
|
||
this._extent = new Vector3();
|
||
this._boundBox = new BoundBox(new Vector3(), new Vector3());
|
||
min.cloneTo(this._boundBox.min);
|
||
max.cloneTo(this._boundBox.max);
|
||
this._setUpdateFlag(Bounds._UPDATE_CENTER | Bounds._UPDATE_EXTENT, true);
|
||
}
|
||
setMin(value) {
|
||
var min = this._boundBox.min;
|
||
if (value !== min)
|
||
value.cloneTo(min);
|
||
this._setUpdateFlag(Bounds._UPDATE_CENTER | Bounds._UPDATE_EXTENT, true);
|
||
this._setUpdateFlag(Bounds._UPDATE_MIN, false);
|
||
}
|
||
getMin() {
|
||
var min = this._boundBox.min;
|
||
if (this._getUpdateFlag(Bounds._UPDATE_MIN)) {
|
||
this._getMin(this.getCenter(), this.getExtent(), min);
|
||
this._setUpdateFlag(Bounds._UPDATE_MIN, false);
|
||
}
|
||
return min;
|
||
}
|
||
setMax(value) {
|
||
var max = this._boundBox.max;
|
||
if (value !== max)
|
||
value.cloneTo(max);
|
||
this._setUpdateFlag(Bounds._UPDATE_CENTER | Bounds._UPDATE_EXTENT, true);
|
||
this._setUpdateFlag(Bounds._UPDATE_MAX, false);
|
||
}
|
||
getMax() {
|
||
var max = this._boundBox.max;
|
||
if (this._getUpdateFlag(Bounds._UPDATE_MAX)) {
|
||
this._getMax(this.getCenter(), this.getExtent(), max);
|
||
this._setUpdateFlag(Bounds._UPDATE_MAX, false);
|
||
}
|
||
return max;
|
||
}
|
||
setCenter(value) {
|
||
if (value !== this._center)
|
||
value.cloneTo(this._center);
|
||
this._setUpdateFlag(Bounds._UPDATE_MIN | Bounds._UPDATE_MAX, true);
|
||
this._setUpdateFlag(Bounds._UPDATE_CENTER, false);
|
||
}
|
||
getCenter() {
|
||
if (this._getUpdateFlag(Bounds._UPDATE_CENTER)) {
|
||
this._getCenter(this.getMin(), this.getMax(), this._center);
|
||
this._setUpdateFlag(Bounds._UPDATE_CENTER, false);
|
||
}
|
||
return this._center;
|
||
}
|
||
setExtent(value) {
|
||
if (value !== this._extent)
|
||
value.cloneTo(this._extent);
|
||
this._setUpdateFlag(Bounds._UPDATE_MIN | Bounds._UPDATE_MAX, true);
|
||
this._setUpdateFlag(Bounds._UPDATE_EXTENT, false);
|
||
}
|
||
getExtent() {
|
||
if (this._getUpdateFlag(Bounds._UPDATE_EXTENT)) {
|
||
this._getExtent(this.getMin(), this.getMax(), this._extent);
|
||
this._setUpdateFlag(Bounds._UPDATE_EXTENT, false);
|
||
}
|
||
return this._extent;
|
||
}
|
||
_getUpdateFlag(type) {
|
||
return (this._updateFlag & type) != 0;
|
||
}
|
||
_setUpdateFlag(type, value) {
|
||
if (value)
|
||
this._updateFlag |= type;
|
||
else
|
||
this._updateFlag &= ~type;
|
||
}
|
||
_getCenter(min, max, out) {
|
||
Vector3.add(min, max, out);
|
||
Vector3.scale(out, 0.5, out);
|
||
}
|
||
_getExtent(min, max, out) {
|
||
Vector3.subtract(max, min, out);
|
||
Vector3.scale(out, 0.5, out);
|
||
}
|
||
_getMin(center, extent, out) {
|
||
Vector3.subtract(center, extent, out);
|
||
}
|
||
_getMax(center, extent, out) {
|
||
Vector3.add(center, extent, out);
|
||
}
|
||
_rotateExtents(extents, rotation, out) {
|
||
var extentsX = extents.x;
|
||
var extentsY = extents.y;
|
||
var extentsZ = extents.z;
|
||
var matE = rotation.elements;
|
||
out.x = Math.abs(matE[0] * extentsX) + Math.abs(matE[4] * extentsY) + Math.abs(matE[8] * extentsZ);
|
||
out.y = Math.abs(matE[1] * extentsX) + Math.abs(matE[5] * extentsY) + Math.abs(matE[9] * extentsZ);
|
||
out.z = Math.abs(matE[2] * extentsX) + Math.abs(matE[6] * extentsY) + Math.abs(matE[10] * extentsZ);
|
||
}
|
||
_tranform(matrix, out) {
|
||
var outCen = out._center;
|
||
var outExt = out._extent;
|
||
Vector3.transformCoordinate(this.getCenter(), matrix, outCen);
|
||
this._rotateExtents(this.getExtent(), matrix, outExt);
|
||
out._boundBox.setCenterAndExtent(outCen, outExt);
|
||
out._updateFlag = 0;
|
||
}
|
||
_getBoundBox() {
|
||
if (this._updateFlag & Bounds._UPDATE_MIN) {
|
||
var min = this._boundBox.min;
|
||
this._getMin(this.getCenter(), this.getExtent(), min);
|
||
this._setUpdateFlag(Bounds._UPDATE_MIN, false);
|
||
}
|
||
if (this._updateFlag & Bounds._UPDATE_MAX) {
|
||
var max = this._boundBox.max;
|
||
this._getMax(this.getCenter(), this.getExtent(), max);
|
||
this._setUpdateFlag(Bounds._UPDATE_MAX, false);
|
||
}
|
||
return this._boundBox;
|
||
}
|
||
calculateBoundsintersection(bounds) {
|
||
var ownMax = this.getMax();
|
||
var ownMin = this.getMin();
|
||
var calMax = bounds.getMax();
|
||
var calMin = bounds.getMin();
|
||
var tempV0 = Bounds.TEMP_VECTOR3_MAX0;
|
||
var tempV1 = Bounds.TEMP_VECTOR3_MAX1;
|
||
var thisExtends = this.getExtent();
|
||
var boundExtends = bounds.getExtent();
|
||
tempV0.setValue(Math.max(ownMax.x, calMax.x) - Math.min(ownMin.x, calMin.x), Math.max(ownMax.y, calMax.y) - Math.min(ownMin.y, calMin.y), Math.max(ownMax.z, calMax.z) - Math.min(ownMin.z, calMin.z));
|
||
tempV1.setValue((thisExtends.x + boundExtends.x) * 2.0, (thisExtends.y + boundExtends.y) * 2.0, (thisExtends.z + boundExtends.z) * 2.0);
|
||
if ((tempV0.x) > (tempV1.x))
|
||
return -1;
|
||
if ((tempV0.y) > (tempV1.y))
|
||
return -1;
|
||
if ((tempV0.z) > (tempV1.z))
|
||
return -1;
|
||
return (tempV1.x - tempV0.x) * (tempV1.y - tempV0.y) * (tempV1.z - tempV0.z);
|
||
}
|
||
cloneTo(destObject) {
|
||
var destBounds = destObject;
|
||
this.getMin().cloneTo(destBounds._boundBox.min);
|
||
this.getMax().cloneTo(destBounds._boundBox.max);
|
||
this.getCenter().cloneTo(destBounds._center);
|
||
this.getExtent().cloneTo(destBounds._extent);
|
||
destBounds._updateFlag = 0;
|
||
}
|
||
clone() {
|
||
var dest = new Bounds(new Vector3(), new Vector3());
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
}
|
||
Bounds._UPDATE_MIN = 0x01;
|
||
Bounds._UPDATE_MAX = 0x02;
|
||
Bounds._UPDATE_CENTER = 0x04;
|
||
Bounds._UPDATE_EXTENT = 0x08;
|
||
Bounds.TEMP_VECTOR3_MAX0 = new Vector3();
|
||
Bounds.TEMP_VECTOR3_MAX1 = new Vector3();
|
||
|
||
class GeometryElement {
|
||
constructor() {
|
||
this._destroyed = false;
|
||
}
|
||
get destroyed() {
|
||
return this._destroyed;
|
||
}
|
||
_getType() {
|
||
throw "GeometryElement:must override it.";
|
||
}
|
||
_prepareRender(state) {
|
||
return true;
|
||
}
|
||
_render(state) {
|
||
throw "GeometryElement:must override it.";
|
||
}
|
||
destroy() {
|
||
if (this._destroyed)
|
||
return;
|
||
this._destroyed = true;
|
||
}
|
||
}
|
||
GeometryElement._typeCounter = 0;
|
||
|
||
class PixelLineVertex {
|
||
constructor() {
|
||
}
|
||
static get vertexDeclaration() {
|
||
return PixelLineVertex._vertexDeclaration;
|
||
}
|
||
static __init__() {
|
||
PixelLineVertex._vertexDeclaration = new VertexDeclaration(28, [new VertexElement(0, VertexElementFormat.Vector3, VertexMesh.MESH_POSITION0),
|
||
new VertexElement(12, VertexElementFormat.Vector4, VertexMesh.MESH_COLOR0)]);
|
||
}
|
||
get vertexDeclaration() {
|
||
return PixelLineVertex._vertexDeclaration;
|
||
}
|
||
}
|
||
|
||
class PixelLineFilter extends GeometryElement {
|
||
constructor(owner, maxLineCount) {
|
||
super();
|
||
this._floatCountPerVertices = 7;
|
||
this._minUpdate = Number.MAX_VALUE;
|
||
this._maxUpdate = Number.MIN_VALUE;
|
||
this._bufferState = new BufferState();
|
||
this._floatBound = new Float32Array(6);
|
||
this._calculateBound = false;
|
||
this._maxLineCount = 0;
|
||
this._lineCount = 0;
|
||
var pointCount = maxLineCount * 2;
|
||
this._owner = owner;
|
||
this._maxLineCount = maxLineCount;
|
||
this._vertices = new Float32Array(pointCount * this._floatCountPerVertices);
|
||
this._vertexBuffer = new VertexBuffer3D(PixelLineVertex.vertexDeclaration.vertexStride * pointCount, Laya.LayaGL.instance.STATIC_DRAW, false);
|
||
this._vertexBuffer.vertexDeclaration = PixelLineVertex.vertexDeclaration;
|
||
this._bufferState.bind();
|
||
this._bufferState.applyVertexBuffer(this._vertexBuffer);
|
||
this._bufferState.unBind();
|
||
var min = PixelLineFilter._tempVector0;
|
||
var max = PixelLineFilter._tempVector1;
|
||
min.setValue(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
|
||
max.setValue(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
|
||
this._bounds = new Bounds(min, max);
|
||
}
|
||
_getType() {
|
||
return PixelLineFilter._type;
|
||
}
|
||
_resizeLineData(maxCount) {
|
||
var pointCount = maxCount * 2;
|
||
var lastVertices = this._vertices;
|
||
this._vertexBuffer.destroy();
|
||
this._maxLineCount = maxCount;
|
||
var vertexCount = pointCount * this._floatCountPerVertices;
|
||
this._vertices = new Float32Array(vertexCount);
|
||
this._vertexBuffer = new VertexBuffer3D(PixelLineVertex.vertexDeclaration.vertexStride * pointCount, Laya.LayaGL.instance.STATIC_DRAW, false);
|
||
this._vertexBuffer.vertexDeclaration = PixelLineVertex.vertexDeclaration;
|
||
if (vertexCount < lastVertices.length) {
|
||
this._vertices.set(new Float32Array(lastVertices.buffer, 0, vertexCount));
|
||
this._vertexBuffer.setData(this._vertices.buffer, 0, 0, vertexCount * 4);
|
||
}
|
||
else {
|
||
this._vertices.set(lastVertices);
|
||
this._vertexBuffer.setData(this._vertices.buffer, 0, 0, lastVertices.length * 4);
|
||
}
|
||
this._bufferState.bind();
|
||
this._bufferState.applyVertexBuffer(this._vertexBuffer);
|
||
this._bufferState.unBind();
|
||
this._minUpdate = Number.MAX_VALUE;
|
||
this._maxUpdate = Number.MIN_VALUE;
|
||
}
|
||
_updateLineVertices(offset, startPosition, endPosition, startColor, endColor) {
|
||
if (startPosition) {
|
||
this._vertices[offset + 0] = startPosition.x;
|
||
this._vertices[offset + 1] = startPosition.y;
|
||
this._vertices[offset + 2] = startPosition.z;
|
||
}
|
||
if (startColor) {
|
||
this._vertices[offset + 3] = startColor.r;
|
||
this._vertices[offset + 4] = startColor.g;
|
||
this._vertices[offset + 5] = startColor.b;
|
||
this._vertices[offset + 6] = startColor.a;
|
||
}
|
||
if (endPosition) {
|
||
this._vertices[offset + 7] = endPosition.x;
|
||
this._vertices[offset + 8] = endPosition.y;
|
||
this._vertices[offset + 9] = endPosition.z;
|
||
}
|
||
if (endColor) {
|
||
this._vertices[offset + 10] = endColor.r;
|
||
this._vertices[offset + 11] = endColor.g;
|
||
this._vertices[offset + 12] = endColor.b;
|
||
this._vertices[offset + 13] = endColor.a;
|
||
}
|
||
this._minUpdate = Math.min(this._minUpdate, offset);
|
||
this._maxUpdate = Math.max(this._maxUpdate, offset + this._floatCountPerVertices * 2);
|
||
var bounds = this._bounds;
|
||
var floatBound = this._floatBound;
|
||
var min = bounds.getMin(), max = bounds.getMax();
|
||
Vector3.min(min, startPosition, min);
|
||
Vector3.min(min, endPosition, min);
|
||
Vector3.max(max, startPosition, max);
|
||
Vector3.max(max, endPosition, max);
|
||
bounds.setMin(min);
|
||
bounds.setMax(max);
|
||
floatBound[0] = min.x, floatBound[1] = min.y, floatBound[2] = min.z;
|
||
floatBound[3] = max.x, floatBound[4] = max.y, floatBound[5] = max.z;
|
||
}
|
||
_reCalculateBound() {
|
||
if (this._calculateBound) {
|
||
var vertices = this._vertices;
|
||
var min = PixelLineFilter._tempVector0;
|
||
var max = PixelLineFilter._tempVector1;
|
||
min.setValue(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
|
||
max.setValue(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
|
||
for (var i = 0; i < this._lineCount * 2; ++i) {
|
||
var offset = this._floatCountPerVertices * i;
|
||
var x = vertices[offset + 0], y = vertices[offset + 1], z = vertices[offset + 2];
|
||
min.x = Math.min(x, min.x);
|
||
min.y = Math.min(y, min.y);
|
||
min.z = Math.min(z, min.z);
|
||
max.x = Math.max(x, max.x);
|
||
max.y = Math.max(y, max.y);
|
||
max.z = Math.max(z, max.z);
|
||
}
|
||
this._bounds.setMin(min);
|
||
this._bounds.setMax(max);
|
||
var floatBound = this._floatBound;
|
||
floatBound[0] = min.x, floatBound[1] = min.y, floatBound[2] = min.z;
|
||
floatBound[3] = max.x, floatBound[4] = max.y, floatBound[5] = max.z;
|
||
this._calculateBound = false;
|
||
}
|
||
}
|
||
_removeLineData(index) {
|
||
var floatCount = this._floatCountPerVertices * 2;
|
||
var nextIndex = index + 1;
|
||
var offset = index * floatCount;
|
||
var vertices = this._vertices;
|
||
var rightPartVertices = new Float32Array(vertices.buffer, nextIndex * floatCount * 4, (this._lineCount - nextIndex) * floatCount);
|
||
vertices.set(rightPartVertices, offset);
|
||
this._minUpdate = Math.min(this._minUpdate, offset);
|
||
this._maxUpdate = Math.max(this._maxUpdate, offset + rightPartVertices.length);
|
||
this._lineCount--;
|
||
var floatBound = this._floatBound;
|
||
var startX = vertices[offset], startY = vertices[offset + 1], startZ = vertices[offset + 2];
|
||
var endX = vertices[offset + 7], endY = vertices[offset + 8], endZ = vertices[offset + 9];
|
||
var minX = floatBound[0], minY = floatBound[1], minZ = floatBound[2];
|
||
var maxX = floatBound[3], maxY = floatBound[4], maxZ = floatBound[5];
|
||
if ((startX === minX) || (startX === maxX) || (startY === minY) || (startY === maxY) || (startZ === minZ) || (startZ === maxZ) ||
|
||
(endX === minX) || (endX === maxX) || (endY === minY) || (endY === maxY) || (endZ === minZ) || (endZ === maxZ))
|
||
this._calculateBound = true;
|
||
}
|
||
_updateLineData(index, startPosition, endPosition, startColor, endColor) {
|
||
var floatCount = this._floatCountPerVertices * 2;
|
||
this._updateLineVertices(index * floatCount, startPosition, endPosition, startColor, endColor);
|
||
}
|
||
_updateLineDatas(index, data) {
|
||
var floatCount = this._floatCountPerVertices * 2;
|
||
var count = data.length;
|
||
for (var i = 0; i < count; i++) {
|
||
var line = data[i];
|
||
this._updateLineVertices((index + i) * floatCount, line.startPosition, line.endPosition, line.startColor, line.endColor);
|
||
}
|
||
}
|
||
_getLineData(index, out) {
|
||
var startPosition = out.startPosition;
|
||
var startColor = out.startColor;
|
||
var endPosition = out.endPosition;
|
||
var endColor = out.endColor;
|
||
var vertices = this._vertices;
|
||
var offset = index * this._floatCountPerVertices * 2;
|
||
startPosition.x = vertices[offset + 0];
|
||
startPosition.y = vertices[offset + 1];
|
||
startPosition.z = vertices[offset + 2];
|
||
startColor.r = vertices[offset + 3];
|
||
startColor.g = vertices[offset + 4];
|
||
startColor.b = vertices[offset + 5];
|
||
startColor.a = vertices[offset + 6];
|
||
endPosition.x = vertices[offset + 7];
|
||
endPosition.y = vertices[offset + 8];
|
||
endPosition.z = vertices[offset + 9];
|
||
endColor.r = vertices[offset + 10];
|
||
endColor.g = vertices[offset + 11];
|
||
endColor.b = vertices[offset + 12];
|
||
endColor.a = vertices[offset + 13];
|
||
}
|
||
_prepareRender(state) {
|
||
return true;
|
||
}
|
||
_render(state) {
|
||
if (this._minUpdate !== Number.MAX_VALUE && this._maxUpdate !== Number.MIN_VALUE) {
|
||
this._vertexBuffer.setData(this._vertices.buffer, this._minUpdate * 4, this._minUpdate * 4, (this._maxUpdate - this._minUpdate) * 4);
|
||
this._minUpdate = Number.MAX_VALUE;
|
||
this._maxUpdate = Number.MIN_VALUE;
|
||
}
|
||
if (this._lineCount > 0) {
|
||
this._bufferState.bind();
|
||
var gl = Laya.LayaGL.instance;
|
||
gl.drawArrays(gl.LINES, 0, this._lineCount * 2);
|
||
Laya.Stat.renderBatches++;
|
||
}
|
||
}
|
||
destroy() {
|
||
if (this._destroyed)
|
||
return;
|
||
super.destroy();
|
||
this._bufferState.destroy();
|
||
this._vertexBuffer.destroy();
|
||
this._bufferState = null;
|
||
this._vertexBuffer = null;
|
||
this._vertices = null;
|
||
}
|
||
}
|
||
PixelLineFilter._tempVector0 = new Vector3();
|
||
PixelLineFilter._tempVector1 = new Vector3();
|
||
PixelLineFilter._type = GeometryElement._typeCounter++;
|
||
|
||
class RenderableSprite3D extends Sprite3D {
|
||
constructor(name) {
|
||
super(name);
|
||
}
|
||
static __init__() {
|
||
RenderableSprite3D.SHADERDEFINE_RECEIVE_SHADOW = Shader3D.getDefineByName("RECEIVESHADOW");
|
||
RenderableSprite3D.SAHDERDEFINE_LIGHTMAP = Shader3D.getDefineByName("LIGHTMAP");
|
||
RenderableSprite3D.SHADERDEFINE_LIGHTMAP_DIRECTIONAL = Shader3D.getDefineByName("LIGHTMAP_DIRECTIONAL");
|
||
}
|
||
_onInActive() {
|
||
super._onInActive();
|
||
this._scene._removeRenderObject(this._render);
|
||
}
|
||
_onActive() {
|
||
super._onActive();
|
||
this._scene._addRenderObject(this._render);
|
||
}
|
||
_onActiveInScene() {
|
||
super._onActiveInScene();
|
||
if (ILaya3D.Laya3D._editerEnvironment) {
|
||
var scene = this._scene;
|
||
var pickColor = new Vector4();
|
||
scene._allotPickColorByID(this.id, pickColor);
|
||
scene._pickIdToSprite[this.id] = this;
|
||
this._render._shaderValues.setVector(RenderableSprite3D.PICKCOLOR, pickColor);
|
||
}
|
||
}
|
||
_addToInitStaticBatchManager() {
|
||
}
|
||
_setBelongScene(scene) {
|
||
super._setBelongScene(scene);
|
||
this._render._setBelongScene(scene);
|
||
}
|
||
_setUnBelongScene() {
|
||
if (!this.destroyed) {
|
||
this._render._shaderValues.removeDefine(RenderableSprite3D.SAHDERDEFINE_LIGHTMAP);
|
||
this._render._setUnBelongScene();
|
||
super._setUnBelongScene();
|
||
}
|
||
}
|
||
_changeHierarchyAnimator(animator) {
|
||
if (this._hierarchyAnimator) {
|
||
var renderableSprites = this._hierarchyAnimator._renderableSprites;
|
||
renderableSprites.splice(renderableSprites.indexOf(this), 1);
|
||
}
|
||
if (animator)
|
||
animator._renderableSprites.push(this);
|
||
super._changeHierarchyAnimator(animator);
|
||
}
|
||
destroy(destroyChild = true) {
|
||
super.destroy(destroyChild);
|
||
this._render._destroy();
|
||
this._render = null;
|
||
}
|
||
_create() {
|
||
return new RenderableSprite3D(this.name);
|
||
}
|
||
}
|
||
RenderableSprite3D.LIGHTMAPSCALEOFFSET = Shader3D.propertyNameToID("u_LightmapScaleOffset");
|
||
RenderableSprite3D.LIGHTMAP = Shader3D.propertyNameToID("u_LightMap");
|
||
RenderableSprite3D.LIGHTMAP_DIRECTION = Shader3D.propertyNameToID("u_LightMapDirection");
|
||
RenderableSprite3D.PICKCOLOR = Shader3D.propertyNameToID("u_PickColor");
|
||
RenderableSprite3D.REFLECTIONTEXTURE = Shader3D.propertyNameToID("u_ReflectTexture");
|
||
RenderableSprite3D.REFLECTIONCUBE_HDR_PARAMS = Shader3D.propertyNameToID("u_ReflectCubeHDRParams");
|
||
RenderableSprite3D.REFLECTIONCUBE_PROBEPOSITION = Shader3D.propertyNameToID("u_SpecCubeProbePosition");
|
||
RenderableSprite3D.REFLECTIONCUBE_PROBEBOXMAX = Shader3D.propertyNameToID("u_SpecCubeBoxMax");
|
||
RenderableSprite3D.REFLECTIONCUBE_PROBEBOXMIN = Shader3D.propertyNameToID("u_SpecCubeBoxMin");
|
||
|
||
class BatchMark {
|
||
constructor() {
|
||
this.updateMark = -1;
|
||
this.indexInList = -1;
|
||
this.batched = false;
|
||
}
|
||
}
|
||
|
||
class SubMeshInstanceBatch extends GeometryElement {
|
||
constructor() {
|
||
super();
|
||
this.instanceWorldMatrixData = new Float32Array(SubMeshInstanceBatch.maxInstanceCount * 16);
|
||
this.instanceSimpleAnimatorData = new Float32Array(SubMeshInstanceBatch.maxInstanceCount * 4);
|
||
var gl = Laya.LayaGL.instance;
|
||
this.instanceWorldMatrixBuffer = new VertexBuffer3D(this.instanceWorldMatrixData.length * 4, gl.DYNAMIC_DRAW);
|
||
this.instanceWorldMatrixBuffer.vertexDeclaration = VertexMesh.instanceWorldMatrixDeclaration;
|
||
this.instanceSimpleAnimatorBuffer = new VertexBuffer3D(this.instanceSimpleAnimatorData.length * 4, gl.DYNAMIC_DRAW);
|
||
this.instanceSimpleAnimatorBuffer.vertexDeclaration = VertexMesh.instanceSimpleAnimatorDeclaration;
|
||
}
|
||
static __init__() {
|
||
SubMeshInstanceBatch.instance = new SubMeshInstanceBatch();
|
||
}
|
||
_render(state) {
|
||
var gl = Laya.LayaGL.instance;
|
||
var element = state.renderElement;
|
||
var subMesh = element.instanceSubMesh;
|
||
var count = element.instanceBatchElementList.length;
|
||
var indexCount = subMesh._indexCount;
|
||
subMesh._mesh._instanceBufferState.bind();
|
||
Laya.LayaGL.layaGPUInstance.drawElementsInstanced(gl.TRIANGLES, indexCount, gl.UNSIGNED_SHORT, subMesh._indexStart * 2, count);
|
||
Laya.Stat.renderBatches++;
|
||
Laya.Stat.savedRenderBatches += count - 1;
|
||
Laya.Stat.trianglesFaces += indexCount * count / 3;
|
||
}
|
||
}
|
||
SubMeshInstanceBatch.maxInstanceCount = 1024;
|
||
|
||
class RenderElement {
|
||
constructor() {
|
||
this.renderSubShader = null;
|
||
this.renderType = RenderElement.RENDERTYPE_NORMAL;
|
||
}
|
||
getInvertFront() {
|
||
return this._transform._isFrontFaceInvert;
|
||
}
|
||
setTransform(transform) {
|
||
this._transform = transform;
|
||
}
|
||
setGeometry(geometry) {
|
||
this._geometry = geometry;
|
||
}
|
||
addToOpaqueRenderQueue(context, queue) {
|
||
queue.elements.add(this);
|
||
}
|
||
addToTransparentRenderQueue(context, queue) {
|
||
queue.elements.add(this);
|
||
queue.lastTransparentBatched = false;
|
||
queue.lastTransparentRenderElement = this;
|
||
}
|
||
_update(scene, context, customShader, replacementTag, subshaderIndex = 0) {
|
||
if (this.material) {
|
||
var subShader = this.material._shader.getSubShaderAt(0);
|
||
this.renderSubShader = null;
|
||
if (customShader) {
|
||
if (replacementTag) {
|
||
var oriTag = subShader.getFlag(replacementTag);
|
||
if (oriTag) {
|
||
var customSubShaders = customShader._subShaders;
|
||
for (var k = 0, p = customSubShaders.length; k < p; k++) {
|
||
var customSubShader = customSubShaders[k];
|
||
if (oriTag === customSubShader.getFlag(replacementTag)) {
|
||
this.renderSubShader = customSubShader;
|
||
break;
|
||
}
|
||
}
|
||
if (!this.renderSubShader)
|
||
return;
|
||
}
|
||
else {
|
||
return;
|
||
}
|
||
}
|
||
else {
|
||
this.renderSubShader = customShader.getSubShaderAt(subshaderIndex);
|
||
}
|
||
}
|
||
else {
|
||
this.renderSubShader = subShader;
|
||
}
|
||
var renderQueue = scene._getRenderQueue(this.material.renderQueue);
|
||
if (renderQueue.isTransparent)
|
||
this.addToTransparentRenderQueue(context, renderQueue);
|
||
else
|
||
this.addToOpaqueRenderQueue(context, renderQueue);
|
||
}
|
||
}
|
||
_render(context) {
|
||
var forceInvertFace = context.invertY;
|
||
var lastStateMaterial, lastStateShaderInstance, lastStateRender;
|
||
var updateMark = Camera._updateMark;
|
||
var scene = context.scene;
|
||
var cameraShaderValue = context.cameraShaderValue;
|
||
var transform = this._transform;
|
||
var geometry = this._geometry;
|
||
context.renderElement = this;
|
||
var updateRender = updateMark !== this.render._updateMark || this.renderType !== this.render._updateRenderType;
|
||
if (updateRender) {
|
||
this.render._renderUpdate(context, transform);
|
||
this.render._renderUpdateWithCamera(context, transform);
|
||
this.render._updateMark = updateMark;
|
||
this.render._updateRenderType = this.renderType;
|
||
}
|
||
else {
|
||
if (this.renderType == RenderElement.RENDERTYPE_INSTANCEBATCH) {
|
||
this.render._renderUpdate(context, transform);
|
||
this.render._renderUpdateWithCamera(context, transform);
|
||
}
|
||
}
|
||
var currentPipelineMode = context.pipelineMode;
|
||
if (geometry._prepareRender(context)) {
|
||
var passes = this.renderSubShader._passes;
|
||
for (var j = 0, m = passes.length; j < m; j++) {
|
||
var pass = passes[j];
|
||
if (pass._pipelineMode !== currentPipelineMode)
|
||
continue;
|
||
var comDef = RenderElement._compileDefine;
|
||
scene._shaderValues._defineDatas.cloneTo(comDef);
|
||
comDef.addDefineDatas(this.render._shaderValues._defineDatas);
|
||
comDef.addDefineDatas(this.material._shaderValues._defineDatas);
|
||
var shaderIns = context.shader = pass.withCompile(comDef);
|
||
var switchShader = shaderIns.bind();
|
||
var switchUpdateMark = (updateMark !== shaderIns._uploadMark);
|
||
var uploadScene = (shaderIns._uploadScene !== scene) || switchUpdateMark;
|
||
if (uploadScene || switchShader) {
|
||
shaderIns.uploadUniforms(shaderIns._sceneUniformParamsMap, scene._shaderValues, uploadScene);
|
||
shaderIns._uploadScene = scene;
|
||
}
|
||
var uploadSprite3D = (shaderIns._uploadRender !== this.render || shaderIns._uploadRenderType !== this.renderType) || switchUpdateMark;
|
||
if (uploadSprite3D || switchShader) {
|
||
shaderIns.uploadUniforms(shaderIns._spriteUniformParamsMap, this.render._shaderValues, uploadSprite3D);
|
||
shaderIns._uploadRender = this.render;
|
||
shaderIns._uploadRenderType = this.renderType;
|
||
}
|
||
var uploadCamera = shaderIns._uploadCameraShaderValue !== cameraShaderValue || switchUpdateMark;
|
||
if (uploadCamera || switchShader) {
|
||
shaderIns.uploadUniforms(shaderIns._cameraUniformParamsMap, cameraShaderValue, uploadCamera);
|
||
shaderIns._uploadCameraShaderValue = cameraShaderValue;
|
||
}
|
||
var uploadMaterial = (shaderIns._uploadMaterial !== this.material) || switchUpdateMark;
|
||
if (uploadMaterial || switchShader) {
|
||
shaderIns.uploadUniforms(shaderIns._materialUniformParamsMap, this.material._shaderValues, uploadMaterial);
|
||
shaderIns._uploadMaterial = this.material;
|
||
}
|
||
var matValues = this.material._shaderValues;
|
||
if (lastStateMaterial !== this.material || lastStateShaderInstance !== shaderIns) {
|
||
shaderIns.uploadRenderStateBlendDepth(matValues);
|
||
shaderIns.uploadRenderStateFrontFace(matValues, forceInvertFace, this.getInvertFront());
|
||
lastStateMaterial = this.material;
|
||
lastStateShaderInstance = shaderIns;
|
||
lastStateRender = this.render;
|
||
}
|
||
else {
|
||
if (lastStateRender !== this.render) {
|
||
shaderIns.uploadRenderStateFrontFace(matValues, forceInvertFace, this.getInvertFront());
|
||
lastStateRender = this.render;
|
||
}
|
||
}
|
||
geometry._render(context);
|
||
shaderIns._uploadMark = updateMark;
|
||
}
|
||
}
|
||
if (this.renderType !== RenderElement.RENDERTYPE_NORMAL)
|
||
this.render._revertBatchRenderUpdate(context);
|
||
}
|
||
destroy() {
|
||
this._transform = null;
|
||
this._geometry = null;
|
||
this.material = null;
|
||
this.render = null;
|
||
}
|
||
}
|
||
RenderElement.RENDERTYPE_NORMAL = 0;
|
||
RenderElement.RENDERTYPE_STATICBATCH = 1;
|
||
RenderElement.RENDERTYPE_INSTANCEBATCH = 2;
|
||
RenderElement.RENDERTYPE_VERTEXBATCH = 3;
|
||
RenderElement._compileDefine = new DefineDatas();
|
||
|
||
class SubMeshRenderElement extends RenderElement {
|
||
constructor() {
|
||
super();
|
||
this._dynamicWorldPositionNormalNeedUpdate = true;
|
||
}
|
||
_onWorldMatrixChanged() {
|
||
this._dynamicWorldPositionNormalNeedUpdate = true;
|
||
}
|
||
_computeWorldPositionsAndNormals(positionOffset, normalOffset, multiSubMesh, vertexCount) {
|
||
if (this._dynamicWorldPositionNormalNeedUpdate) {
|
||
var subMesh = this._geometry;
|
||
var vertexBuffer = subMesh._vertexBuffer;
|
||
var vertexFloatCount = vertexBuffer.vertexDeclaration.vertexStride / 4;
|
||
var oriVertexes = vertexBuffer.getFloat32Data();
|
||
var worldMat = this._transform.worldMatrix;
|
||
var rotation = this._transform.rotation;
|
||
var indices = subMesh._indices;
|
||
for (var i = 0; i < vertexCount; i++) {
|
||
var index = multiSubMesh ? indices[i] : i;
|
||
var oriOffset = index * vertexFloatCount;
|
||
var bakeOffset = i * 3;
|
||
Utils3D.transformVector3ArrayToVector3ArrayCoordinate(oriVertexes, oriOffset + positionOffset, worldMat, this._dynamicWorldPositions, bakeOffset);
|
||
(normalOffset !== -1) && (Utils3D.transformVector3ArrayByQuat(oriVertexes, oriOffset + normalOffset, rotation, this._dynamicWorldNormals, bakeOffset));
|
||
}
|
||
this._dynamicWorldPositionNormalNeedUpdate = false;
|
||
}
|
||
}
|
||
setTransform(transform) {
|
||
if (this._transform !== transform) {
|
||
(this._transform) && (this._transform.off(Laya.Event.TRANSFORM_CHANGED, this, this._onWorldMatrixChanged));
|
||
(transform) && (transform.on(Laya.Event.TRANSFORM_CHANGED, this, this._onWorldMatrixChanged));
|
||
this._dynamicWorldPositionNormalNeedUpdate = true;
|
||
this._transform = transform;
|
||
}
|
||
}
|
||
setGeometry(geometry) {
|
||
if (this._geometry !== geometry) {
|
||
var subMesh = geometry;
|
||
var mesh = subMesh._mesh;
|
||
if (mesh) {
|
||
var multiSubMesh = mesh._subMeshes.length > 1;
|
||
var dynBatVerCount = multiSubMesh ? subMesh._indexCount : mesh._vertexCount;
|
||
if (dynBatVerCount <= ILaya3D.SubMeshDynamicBatch.maxAllowVertexCount) {
|
||
var length = dynBatVerCount * 3;
|
||
this._dynamicVertexBatch = true;
|
||
this._dynamicWorldPositions = new Float32Array(length);
|
||
this._dynamicWorldNormals = new Float32Array(length);
|
||
this._dynamicVertexCount = dynBatVerCount;
|
||
this._dynamicMultiSubMesh = multiSubMesh;
|
||
}
|
||
else {
|
||
this._dynamicVertexBatch = false;
|
||
}
|
||
}
|
||
this._geometry = geometry;
|
||
}
|
||
}
|
||
addToOpaqueRenderQueue(context, queue) {
|
||
var subMeshStaticBatch = this.staticBatch;
|
||
var queueElements = queue.elements;
|
||
var elements = queueElements.elements;
|
||
if (subMeshStaticBatch && (!this.render._probReflection || this.render._probReflection._isScene) && SubMeshRenderElement.enableStaticBatch) {
|
||
var staManager = ILaya3D.MeshRenderStaticBatchManager.instance;
|
||
var staBatchMarks = staManager.getBatchOpaquaMark(this.render.lightmapIndex + 1, this.render.receiveShadow, this.material.id, subMeshStaticBatch._batchID);
|
||
if (staManager._updateCountMark === staBatchMarks.updateMark) {
|
||
var staBatchIndex = staBatchMarks.indexInList;
|
||
if (staBatchMarks.batched) {
|
||
elements[staBatchIndex].staticBatchElementList.add(this);
|
||
}
|
||
else {
|
||
var staOriElement = elements[staBatchIndex];
|
||
var staOriRender = staOriElement.render;
|
||
var staBatchElement = staManager._getBatchRenderElementFromPool();
|
||
staBatchElement.renderType = RenderElement.RENDERTYPE_STATICBATCH;
|
||
staBatchElement.setGeometry(subMeshStaticBatch);
|
||
staBatchElement.material = staOriElement.material;
|
||
var staRootOwner = subMeshStaticBatch.batchOwner;
|
||
var staBatchTransform = staRootOwner ? staRootOwner._transform : null;
|
||
staBatchElement.setTransform(staBatchTransform);
|
||
staBatchElement.render = staOriRender;
|
||
staBatchElement.renderSubShader = staOriElement.renderSubShader;
|
||
var staBatchList = staBatchElement.staticBatchElementList;
|
||
staBatchList.length = 0;
|
||
staBatchList.add(staOriElement);
|
||
staBatchList.add(this);
|
||
elements[staBatchIndex] = staBatchElement;
|
||
staBatchMarks.batched = true;
|
||
}
|
||
}
|
||
else {
|
||
staBatchMarks.updateMark = staManager._updateCountMark;
|
||
staBatchMarks.indexInList = queueElements.length;
|
||
staBatchMarks.batched = false;
|
||
queueElements.add(this);
|
||
}
|
||
}
|
||
else if (SubMeshRenderElement.enableDynamicBatch && this.renderSubShader._owner._enableInstancing && Laya.LayaGL.layaGPUInstance.supportInstance() && this.render.lightmapIndex < 0 && (!this.render._probReflection || this.render._probReflection._isScene)) {
|
||
var subMesh = this._geometry;
|
||
var insManager = ILaya3D.MeshRenderDynamicBatchManager.instance;
|
||
var insBatchMarks = insManager.getInstanceBatchOpaquaMark(this.render.receiveShadow, this.material.id, subMesh._id, this._transform._isFrontFaceInvert);
|
||
if (insManager._updateCountMark === insBatchMarks.updateMark) {
|
||
var insBatchIndex = insBatchMarks.indexInList;
|
||
if (insBatchMarks.batched) {
|
||
var instanceBatchElementList = elements[insBatchIndex].instanceBatchElementList;
|
||
if (instanceBatchElementList.length === SubMeshInstanceBatch.maxInstanceCount) {
|
||
insBatchMarks.updateMark = insManager._updateCountMark;
|
||
insBatchMarks.indexInList = queueElements.length;
|
||
insBatchMarks.batched = false;
|
||
queueElements.add(this);
|
||
}
|
||
else {
|
||
instanceBatchElementList.add(this);
|
||
}
|
||
}
|
||
else {
|
||
var insOriElement = elements[insBatchIndex];
|
||
var insOriRender = insOriElement.render;
|
||
var insBatchElement = insManager._getBatchRenderElementFromPool();
|
||
insBatchElement.renderType = RenderElement.RENDERTYPE_INSTANCEBATCH;
|
||
insBatchElement.setGeometry(SubMeshInstanceBatch.instance);
|
||
insBatchElement.material = insOriElement.material;
|
||
insBatchElement.setTransform(null);
|
||
insBatchElement.render = insOriRender;
|
||
insBatchElement.instanceSubMesh = subMesh;
|
||
insBatchElement.renderSubShader = insOriElement.renderSubShader;
|
||
var insBatchList = insBatchElement.instanceBatchElementList;
|
||
insBatchList.length = 0;
|
||
insBatchList.add(insOriElement);
|
||
insBatchList.add(this);
|
||
elements[insBatchIndex] = insBatchElement;
|
||
insBatchMarks.batched = true;
|
||
}
|
||
}
|
||
else {
|
||
insBatchMarks.updateMark = insManager._updateCountMark;
|
||
insBatchMarks.indexInList = queueElements.length;
|
||
insBatchMarks.batched = false;
|
||
queueElements.add(this);
|
||
}
|
||
}
|
||
else if (this._dynamicVertexBatch && SubMeshRenderElement.enableDynamicBatch) {
|
||
var verDec = this._geometry._vertexBuffer.vertexDeclaration;
|
||
var dynManager = ILaya3D.MeshRenderDynamicBatchManager.instance;
|
||
var dynBatchMarks = dynManager.getVertexBatchOpaquaMark(this.render.lightmapIndex + 1, this.render.receiveShadow, this.material.id, verDec.id);
|
||
if (dynManager._updateCountMark === dynBatchMarks.updateMark) {
|
||
var dynBatchIndex = dynBatchMarks.indexInList;
|
||
if (dynBatchMarks.batched) {
|
||
elements[dynBatchIndex].vertexBatchElementList.add(this);
|
||
}
|
||
else {
|
||
var dynOriElement = elements[dynBatchIndex];
|
||
var dynOriRender = dynOriElement.render;
|
||
var dynBatchElement = dynManager._getBatchRenderElementFromPool();
|
||
dynBatchElement.renderType = RenderElement.RENDERTYPE_VERTEXBATCH;
|
||
dynBatchElement.setGeometry(ILaya3D.SubMeshDynamicBatch.instance);
|
||
dynBatchElement.material = dynOriElement.material;
|
||
dynBatchElement.setTransform(null);
|
||
dynBatchElement.render = dynOriRender;
|
||
dynBatchElement.vertexBatchVertexDeclaration = verDec;
|
||
dynBatchElement.renderSubShader = dynOriElement.renderSubShader;
|
||
var dynBatchList = dynBatchElement.vertexBatchElementList;
|
||
dynBatchList.length = 0;
|
||
dynBatchList.add(dynOriElement);
|
||
dynBatchList.add(this);
|
||
elements[dynBatchIndex] = dynBatchElement;
|
||
dynBatchMarks.batched = true;
|
||
}
|
||
}
|
||
else {
|
||
dynBatchMarks.updateMark = dynManager._updateCountMark;
|
||
dynBatchMarks.indexInList = queueElements.length;
|
||
dynBatchMarks.batched = false;
|
||
queueElements.add(this);
|
||
}
|
||
}
|
||
else {
|
||
queueElements.add(this);
|
||
}
|
||
}
|
||
addToTransparentRenderQueue(context, queue) {
|
||
var subMeshStaticBatch = this.staticBatch;
|
||
var queueElements = queue.elements;
|
||
var elements = queueElements.elements;
|
||
if (subMeshStaticBatch && SubMeshRenderElement.enableStaticBatch) {
|
||
var staManager = ILaya3D.MeshRenderStaticBatchManager.instance;
|
||
var staLastElement = queue.lastTransparentRenderElement;
|
||
if (staLastElement) {
|
||
var staLastRender = staLastElement.render;
|
||
if (staLastElement._geometry._getType() !== this._geometry._getType() || staLastElement.staticBatch !== subMeshStaticBatch || staLastElement.material !== this.material || staLastRender.receiveShadow !== this.render.receiveShadow || staLastRender.lightmapIndex !== this.render.lightmapIndex) {
|
||
queueElements.add(this);
|
||
queue.lastTransparentBatched = false;
|
||
}
|
||
else {
|
||
if (queue.lastTransparentBatched) {
|
||
elements[queueElements.length - 1].staticBatchElementList.add((this));
|
||
}
|
||
else {
|
||
var staBatchElement = staManager._getBatchRenderElementFromPool();
|
||
staBatchElement.renderType = RenderElement.RENDERTYPE_STATICBATCH;
|
||
staBatchElement.setGeometry(subMeshStaticBatch);
|
||
staBatchElement.material = staLastElement.material;
|
||
var staRootOwner = subMeshStaticBatch.batchOwner;
|
||
var staBatchTransform = staRootOwner ? staRootOwner._transform : null;
|
||
staBatchElement.setTransform(staBatchTransform);
|
||
staBatchElement.render = this.render;
|
||
staBatchElement.renderSubShader = staLastElement.renderSubShader;
|
||
var staBatchList = staBatchElement.staticBatchElementList;
|
||
staBatchList.length = 0;
|
||
staBatchList.add(staLastElement);
|
||
staBatchList.add(this);
|
||
elements[queueElements.length - 1] = staBatchElement;
|
||
}
|
||
queue.lastTransparentBatched = true;
|
||
}
|
||
}
|
||
else {
|
||
queueElements.add(this);
|
||
queue.lastTransparentBatched = false;
|
||
}
|
||
}
|
||
else if (SubMeshRenderElement.enableDynamicBatch && this.renderSubShader._owner._enableInstancing && Laya.LayaGL.layaGPUInstance.supportInstance() && this.render.lightmapIndex < 0 && (!this.render._probReflection || this.render._probReflection._isScene)) {
|
||
var subMesh = this._geometry;
|
||
var insManager = ILaya3D.MeshRenderDynamicBatchManager.instance;
|
||
var insLastElement = queue.lastTransparentRenderElement;
|
||
if (insLastElement) {
|
||
var insLastRender = insLastElement.render;
|
||
if (insLastElement._geometry._getType() !== this._geometry._getType() || insLastElement._geometry !== subMesh || insLastElement.material !== this.material || insLastRender.receiveShadow !== this.render.receiveShadow) {
|
||
queueElements.add(this);
|
||
queue.lastTransparentBatched = false;
|
||
}
|
||
else {
|
||
if (queue.lastTransparentBatched) {
|
||
var instanceBatchElementList = elements[queueElements.length - 1].instanceBatchElementList;
|
||
if (instanceBatchElementList.length === SubMeshInstanceBatch.maxInstanceCount) {
|
||
queueElements.add(this);
|
||
queue.lastTransparentBatched = false;
|
||
}
|
||
else {
|
||
instanceBatchElementList.add(this);
|
||
queue.lastTransparentBatched = true;
|
||
}
|
||
}
|
||
else {
|
||
var insBatchElement = insManager._getBatchRenderElementFromPool();
|
||
insBatchElement.renderType = RenderElement.RENDERTYPE_INSTANCEBATCH;
|
||
insBatchElement.setGeometry(SubMeshInstanceBatch.instance);
|
||
insBatchElement.material = insLastElement.material;
|
||
insBatchElement.setTransform(null);
|
||
insBatchElement.render = this.render;
|
||
insBatchElement.instanceSubMesh = subMesh;
|
||
insBatchElement.renderSubShader = insLastElement.renderSubShader;
|
||
var insBatchList = insBatchElement.instanceBatchElementList;
|
||
insBatchList.length = 0;
|
||
insBatchList.add(insLastElement);
|
||
insBatchList.add(this);
|
||
elements[queueElements.length - 1] = insBatchElement;
|
||
queue.lastTransparentBatched = true;
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
queueElements.add(this);
|
||
queue.lastTransparentBatched = false;
|
||
}
|
||
}
|
||
else if (this._dynamicVertexBatch && SubMeshRenderElement.enableDynamicBatch) {
|
||
var verDec = this._geometry._vertexBuffer.vertexDeclaration;
|
||
var dynManager = ILaya3D.MeshRenderDynamicBatchManager.instance;
|
||
var dynLastElement = queue.lastTransparentRenderElement;
|
||
if (dynLastElement) {
|
||
var dynLastRender = dynLastElement.render;
|
||
if (!dynLastElement._dynamicVertexBatch || dynLastElement._geometry._getType() !== this._geometry._getType() || dynLastElement._geometry._vertexBuffer._vertexDeclaration !== verDec || dynLastElement.material !== this.material || dynLastRender.receiveShadow !== this.render.receiveShadow || dynLastRender.lightmapIndex !== this.render.lightmapIndex) {
|
||
queueElements.add(this);
|
||
queue.lastTransparentBatched = false;
|
||
}
|
||
else {
|
||
if (queue.lastTransparentBatched) {
|
||
elements[queueElements.length - 1].vertexBatchElementList.add((this));
|
||
}
|
||
else {
|
||
var dynBatchElement = dynManager._getBatchRenderElementFromPool();
|
||
dynBatchElement.renderType = RenderElement.RENDERTYPE_VERTEXBATCH;
|
||
dynBatchElement.setGeometry(ILaya3D.SubMeshDynamicBatch.instance);
|
||
dynBatchElement.material = dynLastElement.material;
|
||
dynBatchElement.setTransform(null);
|
||
dynBatchElement.render = this.render;
|
||
dynBatchElement.vertexBatchVertexDeclaration = verDec;
|
||
dynBatchElement.renderSubShader = dynLastElement.renderSubShader;
|
||
var dynBatchList = dynBatchElement.vertexBatchElementList;
|
||
dynBatchList.length = 0;
|
||
dynBatchList.add(dynLastElement);
|
||
dynBatchList.add(this);
|
||
elements[queueElements.length - 1] = dynBatchElement;
|
||
}
|
||
queue.lastTransparentBatched = true;
|
||
}
|
||
}
|
||
else {
|
||
queueElements.add(this);
|
||
queue.lastTransparentBatched = false;
|
||
}
|
||
}
|
||
else {
|
||
queueElements.add(this);
|
||
}
|
||
queue.lastTransparentRenderElement = this;
|
||
}
|
||
getInvertFront() {
|
||
switch (this.renderType) {
|
||
case RenderElement.RENDERTYPE_NORMAL:
|
||
return this._transform._isFrontFaceInvert;
|
||
case RenderElement.RENDERTYPE_STATICBATCH:
|
||
case RenderElement.RENDERTYPE_VERTEXBATCH:
|
||
return false;
|
||
case RenderElement.RENDERTYPE_INSTANCEBATCH:
|
||
return this.instanceBatchElementList.elements[0]._transform._isFrontFaceInvert;
|
||
default:
|
||
throw "SubMeshRenderElement: unknown renderType";
|
||
}
|
||
}
|
||
destroy() {
|
||
super.destroy();
|
||
this._dynamicWorldPositions = null;
|
||
this._dynamicWorldNormals = null;
|
||
this.staticBatch = null;
|
||
this.staticBatchElementList = null;
|
||
this.vertexBatchElementList = null;
|
||
this.vertexBatchVertexDeclaration = null;
|
||
}
|
||
}
|
||
SubMeshRenderElement.enableDynamicBatch = true;
|
||
SubMeshRenderElement.enableStaticBatch = true;
|
||
|
||
class StaticBatchManager {
|
||
constructor() {
|
||
this._initBatchSprites = [];
|
||
this._staticBatches = {};
|
||
this._batchRenderElementPoolIndex = 0;
|
||
this._batchRenderElementPool = [];
|
||
}
|
||
static _addToStaticBatchQueue(sprite3D, renderableSprite3D) {
|
||
if (sprite3D instanceof RenderableSprite3D)
|
||
renderableSprite3D.push(sprite3D);
|
||
for (var i = 0, n = sprite3D.numChildren; i < n; i++)
|
||
StaticBatchManager._addToStaticBatchQueue(sprite3D._children[i], renderableSprite3D);
|
||
}
|
||
static _registerManager(manager) {
|
||
StaticBatchManager._managers.push(manager);
|
||
}
|
||
static combine(staticBatchRoot, renderableSprite3Ds = null) {
|
||
if (!renderableSprite3Ds) {
|
||
renderableSprite3Ds = [];
|
||
if (staticBatchRoot)
|
||
StaticBatchManager._addToStaticBatchQueue(staticBatchRoot, renderableSprite3Ds);
|
||
}
|
||
var batchSpritesCount = renderableSprite3Ds.length;
|
||
if (batchSpritesCount > 0) {
|
||
for (var i = 0; i < batchSpritesCount; i++) {
|
||
var sprite = renderableSprite3Ds[i];
|
||
if (!sprite.destroyed) {
|
||
if (sprite._render._isPartOfStaticBatch)
|
||
console.warn("StaticBatchManager: Sprite " + sprite.name + " has a part of Static Batch,it will be ignore.");
|
||
else
|
||
sprite._addToInitStaticBatchManager();
|
||
}
|
||
}
|
||
for (var k = 0, m = StaticBatchManager._managers.length; k < m; k++) {
|
||
var manager = StaticBatchManager._managers[k];
|
||
manager._initStaticBatchs(staticBatchRoot);
|
||
}
|
||
}
|
||
}
|
||
_partition(items, left, right) {
|
||
var pivot = items[Math.floor((right + left) / 2)];
|
||
while (left <= right) {
|
||
while (this._compare(items[left], pivot) < 0)
|
||
left++;
|
||
while (this._compare(items[right], pivot) > 0)
|
||
right--;
|
||
if (left < right) {
|
||
var temp = items[left];
|
||
items[left] = items[right];
|
||
items[right] = temp;
|
||
left++;
|
||
right--;
|
||
}
|
||
else if (left === right) {
|
||
left++;
|
||
break;
|
||
}
|
||
}
|
||
return left;
|
||
}
|
||
_quickSort(items, left, right) {
|
||
if (items.length > 1) {
|
||
var index = this._partition(items, left, right);
|
||
var leftIndex = index - 1;
|
||
if (left < leftIndex)
|
||
this._quickSort(items, left, leftIndex);
|
||
if (index < right)
|
||
this._quickSort(items, index, right);
|
||
}
|
||
}
|
||
_compare(left, right) {
|
||
throw "StaticBatch:must override this function.";
|
||
}
|
||
_initStaticBatchs(rootSprite) {
|
||
throw "StaticBatch:must override this function.";
|
||
}
|
||
_getBatchRenderElementFromPool() {
|
||
throw "StaticBatch:must override this function.";
|
||
}
|
||
_addBatchSprite(renderableSprite3D) {
|
||
this._initBatchSprites.push(renderableSprite3D);
|
||
}
|
||
_clear() {
|
||
this._batchRenderElementPoolIndex = 0;
|
||
}
|
||
_garbageCollection() {
|
||
throw "StaticBatchManager: must override it.";
|
||
}
|
||
dispose() {
|
||
this._staticBatches = null;
|
||
}
|
||
}
|
||
StaticBatchManager._managers = [];
|
||
|
||
class SubMeshStaticBatch extends GeometryElement {
|
||
constructor(batchOwner, vertexDeclaration) {
|
||
super();
|
||
this._bufferState = new BufferState();
|
||
this._batchID = SubMeshStaticBatch._batchIDCounter++;
|
||
this._batchElements = [];
|
||
this._currentBatchVertexCount = 0;
|
||
this._currentBatchIndexCount = 0;
|
||
this._vertexDeclaration = vertexDeclaration;
|
||
this.batchOwner = batchOwner;
|
||
}
|
||
_getStaticBatchBakedVertexs(batchVertices, batchOffset, batchOwnerTransform, transform, render, mesh) {
|
||
var vertexBuffer = mesh._vertexBuffer;
|
||
var vertexDeclaration = vertexBuffer.vertexDeclaration;
|
||
var positionOffset = vertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_POSITION0)._offset / 4;
|
||
var normalElement = vertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_NORMAL0);
|
||
var normalOffset = normalElement ? normalElement._offset / 4 : -1;
|
||
var colorElement = vertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_COLOR0);
|
||
var colorOffset = colorElement ? colorElement._offset / 4 : -1;
|
||
var uv0Element = vertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_TEXTURECOORDINATE0);
|
||
var uv0Offset = uv0Element ? uv0Element._offset / 4 : -1;
|
||
var uv1Element = vertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_TEXTURECOORDINATE1);
|
||
var uv1Offset = uv1Element ? uv1Element._offset / 4 : -1;
|
||
var tangentElement = vertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_TANGENT0);
|
||
var sTangentOffset = tangentElement ? tangentElement._offset / 4 : -1;
|
||
var bakeVertexFloatCount = 18;
|
||
var oriVertexFloatCount = vertexDeclaration.vertexStride / 4;
|
||
var oriVertexes = vertexBuffer.getFloat32Data();
|
||
var worldMat;
|
||
if (batchOwnerTransform) {
|
||
var rootMat = batchOwnerTransform.worldMatrix;
|
||
rootMat.invert(SubMeshStaticBatch._tempMatrix4x40);
|
||
worldMat = SubMeshStaticBatch._tempMatrix4x41;
|
||
Matrix4x4.multiply(SubMeshStaticBatch._tempMatrix4x40, transform.worldMatrix, worldMat);
|
||
}
|
||
else {
|
||
worldMat = transform.worldMatrix;
|
||
}
|
||
var normalMat = SubMeshStaticBatch._tempMatrix4x42;
|
||
worldMat.invert(normalMat);
|
||
normalMat.transpose();
|
||
var rotation = SubMeshStaticBatch._tempQuaternion0;
|
||
worldMat.decomposeTransRotScale(SubMeshStaticBatch._tempVector30, rotation, SubMeshStaticBatch._tempVector31);
|
||
var lightmapScaleOffset = render.lightmapScaleOffset;
|
||
var vertexCount = mesh.vertexCount;
|
||
for (var i = 0; i < vertexCount; i++) {
|
||
var oriOffset = i * oriVertexFloatCount;
|
||
var bakeOffset = (i + batchOffset) * bakeVertexFloatCount;
|
||
Utils3D.transformVector3ArrayToVector3ArrayCoordinate(oriVertexes, oriOffset + positionOffset, worldMat, batchVertices, bakeOffset + 0);
|
||
if (normalOffset !== -1)
|
||
Utils3D.transformVector3ArrayToVector3ArrayNormal(oriVertexes, oriOffset + normalOffset, normalMat, batchVertices, bakeOffset + 3);
|
||
var j, m;
|
||
var bakOff = bakeOffset + 6;
|
||
if (colorOffset !== -1) {
|
||
var oriOff = oriOffset + colorOffset;
|
||
for (j = 0, m = 4; j < m; j++)
|
||
batchVertices[bakOff + j] = oriVertexes[oriOff + j];
|
||
}
|
||
else {
|
||
for (j = 0, m = 4; j < m; j++)
|
||
batchVertices[bakOff + j] = 1.0;
|
||
}
|
||
if (uv0Offset !== -1) {
|
||
var absUv0Offset = oriOffset + uv0Offset;
|
||
batchVertices[bakeOffset + 10] = oriVertexes[absUv0Offset];
|
||
batchVertices[bakeOffset + 11] = oriVertexes[absUv0Offset + 1];
|
||
}
|
||
if (lightmapScaleOffset) {
|
||
if (uv1Offset !== -1)
|
||
Utils3D.transformLightingMapTexcoordArray(oriVertexes, oriOffset + uv1Offset, lightmapScaleOffset, batchVertices, bakeOffset + 12);
|
||
else
|
||
Utils3D.transformLightingMapTexcoordArray(oriVertexes, oriOffset + uv0Offset, lightmapScaleOffset, batchVertices, bakeOffset + 12);
|
||
}
|
||
if (sTangentOffset !== -1) {
|
||
var absSTanegntOffset = oriOffset + sTangentOffset;
|
||
Utils3D.transformVector3ArrayToVector3ArrayNormal(oriVertexes, absSTanegntOffset, normalMat, batchVertices, bakeOffset + 14);
|
||
batchVertices[bakeOffset + 17] = oriVertexes[absSTanegntOffset + 3];
|
||
}
|
||
}
|
||
return vertexCount;
|
||
}
|
||
addTest(sprite) {
|
||
var vertexCount;
|
||
var subMeshVertexCount = sprite.meshFilter.sharedMesh.vertexCount;
|
||
vertexCount = this._currentBatchVertexCount + subMeshVertexCount;
|
||
if (vertexCount > SubMeshStaticBatch.maxBatchVertexCount)
|
||
return false;
|
||
return true;
|
||
}
|
||
add(sprite) {
|
||
var mesh = sprite.meshFilter.sharedMesh;
|
||
var subMeshVertexCount = mesh.vertexCount;
|
||
this._batchElements.push(sprite);
|
||
var render = sprite._render;
|
||
render._isPartOfStaticBatch = true;
|
||
render._staticBatch = this;
|
||
var renderElements = render._renderElements;
|
||
for (var i = 0, n = renderElements.length; i < n; i++)
|
||
renderElements[i].staticBatch = this;
|
||
this._currentBatchIndexCount += mesh._indexBuffer.indexCount;
|
||
this._currentBatchVertexCount += subMeshVertexCount;
|
||
}
|
||
remove(sprite) {
|
||
var mesh = sprite.meshFilter.sharedMesh;
|
||
var index = this._batchElements.indexOf(sprite);
|
||
if (index !== -1) {
|
||
this._batchElements.splice(index, 1);
|
||
var renderElements = sprite._render._renderElements;
|
||
for (var i = 0, n = renderElements.length; i < n; i++)
|
||
renderElements[i].staticBatch = null;
|
||
this._currentBatchIndexCount = this._currentBatchIndexCount - mesh._indexBuffer.indexCount;
|
||
this._currentBatchVertexCount = this._currentBatchVertexCount - mesh.vertexCount;
|
||
sprite._render._isPartOfStaticBatch = false;
|
||
}
|
||
}
|
||
finishInit() {
|
||
if (this._vertexBuffer) {
|
||
this._vertexBuffer.destroy();
|
||
this._indexBuffer.destroy();
|
||
Laya.Resource._addGPUMemory(-(this._vertexBuffer._byteLength + this._indexBuffer._byteLength));
|
||
}
|
||
var gl = Laya.LayaGL.instance;
|
||
var batchVertexCount = 0;
|
||
var batchIndexCount = 0;
|
||
var rootOwner = this.batchOwner;
|
||
var floatStride = this._vertexDeclaration.vertexStride / 4;
|
||
var vertexDatas = new Float32Array(floatStride * this._currentBatchVertexCount);
|
||
var indexDatas = new Uint16Array(this._currentBatchIndexCount);
|
||
this._vertexBuffer = new VertexBuffer3D(this._vertexDeclaration.vertexStride * this._currentBatchVertexCount, gl.STATIC_DRAW);
|
||
this._vertexBuffer.vertexDeclaration = this._vertexDeclaration;
|
||
this._indexBuffer = new IndexBuffer3D(exports.IndexFormat.UInt16, this._currentBatchIndexCount, gl.STATIC_DRAW);
|
||
for (var i = 0, n = this._batchElements.length; i < n; i++) {
|
||
var sprite = this._batchElements[i];
|
||
var mesh = sprite.meshFilter.sharedMesh;
|
||
var meshVerCount = this._getStaticBatchBakedVertexs(vertexDatas, batchVertexCount, rootOwner ? rootOwner._transform : null, sprite._transform, sprite._render, mesh);
|
||
var indices = mesh._indexBuffer.getData();
|
||
var indexOffset = batchVertexCount;
|
||
var indexEnd = batchIndexCount + indices.length;
|
||
var elements = sprite._render._renderElements;
|
||
for (var j = 0, m = mesh.subMeshCount; j < m; j++) {
|
||
var subMesh = mesh._subMeshes[j];
|
||
var start = batchIndexCount + subMesh._indexStart;
|
||
var element = elements[j];
|
||
element.staticBatchIndexStart = start;
|
||
element.staticBatchIndexEnd = start + subMesh._indexCount;
|
||
}
|
||
indexDatas.set(indices, batchIndexCount);
|
||
var k;
|
||
var isInvert = rootOwner ? (sprite._transform._isFrontFaceInvert !== rootOwner.transform._isFrontFaceInvert) : sprite._transform._isFrontFaceInvert;
|
||
if (isInvert) {
|
||
for (k = batchIndexCount; k < indexEnd; k += 3) {
|
||
indexDatas[k] = indexOffset + indexDatas[k];
|
||
var index1 = indexDatas[k + 1];
|
||
var index2 = indexDatas[k + 2];
|
||
indexDatas[k + 1] = indexOffset + index2;
|
||
indexDatas[k + 2] = indexOffset + index1;
|
||
}
|
||
}
|
||
else {
|
||
for (k = batchIndexCount; k < indexEnd; k += 3) {
|
||
indexDatas[k] = indexOffset + indexDatas[k];
|
||
indexDatas[k + 1] = indexOffset + indexDatas[k + 1];
|
||
indexDatas[k + 2] = indexOffset + indexDatas[k + 2];
|
||
}
|
||
}
|
||
batchIndexCount += indices.length;
|
||
batchVertexCount += meshVerCount;
|
||
}
|
||
this._vertexBuffer.setData(vertexDatas.buffer);
|
||
this._indexBuffer.setData(indexDatas);
|
||
var memorySize = this._vertexBuffer._byteLength + this._indexBuffer._byteLength;
|
||
Laya.Resource._addGPUMemory(memorySize);
|
||
this._bufferState.bind();
|
||
this._bufferState.applyVertexBuffer(this._vertexBuffer);
|
||
this._bufferState.applyIndexBuffer(this._indexBuffer);
|
||
this._bufferState.unBind();
|
||
}
|
||
_render(state) {
|
||
this._bufferState.bind();
|
||
var gl = Laya.LayaGL.instance;
|
||
var element = state.renderElement;
|
||
var staticBatchElementList = element.staticBatchElementList;
|
||
var batchElementList = staticBatchElementList.elements;
|
||
var from = 0;
|
||
var end = 0;
|
||
var count = staticBatchElementList.length;
|
||
for (var i = 1; i < count; i++) {
|
||
var lastElement = batchElementList[i - 1];
|
||
if (lastElement.staticBatchIndexEnd === batchElementList[i].staticBatchIndexStart) {
|
||
end++;
|
||
continue;
|
||
}
|
||
else {
|
||
var start = batchElementList[from].staticBatchIndexStart;
|
||
var indexCount = batchElementList[end].staticBatchIndexEnd - start;
|
||
gl.drawElements(gl.TRIANGLES, indexCount, gl.UNSIGNED_SHORT, start * 2);
|
||
from = ++end;
|
||
Laya.Stat.trianglesFaces += indexCount / 3;
|
||
}
|
||
}
|
||
start = batchElementList[from].staticBatchIndexStart;
|
||
indexCount = batchElementList[end].staticBatchIndexEnd - start;
|
||
gl.drawElements(gl.TRIANGLES, indexCount, gl.UNSIGNED_SHORT, start * 2);
|
||
Laya.Stat.renderBatches++;
|
||
Laya.Stat.savedRenderBatches += count - 1;
|
||
Laya.Stat.trianglesFaces += indexCount / 3;
|
||
}
|
||
dispose() {
|
||
var memorySize = this._vertexBuffer._byteLength + this._indexBuffer._byteLength;
|
||
Laya.Resource._addGPUMemory(-memorySize);
|
||
this._batchElements = null;
|
||
this.batchOwner = null;
|
||
this._vertexDeclaration = null;
|
||
this._bufferState.destroy();
|
||
this._vertexBuffer.destroy();
|
||
this._indexBuffer.destroy();
|
||
this._vertexBuffer = null;
|
||
this._indexBuffer = null;
|
||
this._bufferState = null;
|
||
}
|
||
}
|
||
SubMeshStaticBatch._tempVector30 = new Vector3();
|
||
SubMeshStaticBatch._tempVector31 = new Vector3();
|
||
SubMeshStaticBatch._tempQuaternion0 = new Quaternion();
|
||
SubMeshStaticBatch._tempMatrix4x40 = new Matrix4x4();
|
||
SubMeshStaticBatch._tempMatrix4x41 = new Matrix4x4();
|
||
SubMeshStaticBatch._tempMatrix4x42 = new Matrix4x4();
|
||
SubMeshStaticBatch.maxBatchVertexCount = 65535;
|
||
SubMeshStaticBatch._batchIDCounter = 0;
|
||
|
||
class MeshRenderStaticBatchManager extends StaticBatchManager {
|
||
constructor() {
|
||
super();
|
||
this._opaqueBatchMarks = [];
|
||
this._updateCountMark = 0;
|
||
}
|
||
static __init__() {
|
||
MeshRenderStaticBatchManager._verDec = VertexMesh.getVertexDeclaration("POSITION,NORMAL,COLOR,UV,UV1,TANGENT");
|
||
}
|
||
_compare(left, right) {
|
||
var lRender = left._render, rRender = right._render;
|
||
var leftGeo = left.meshFilter.sharedMesh, rightGeo = right.meshFilter.sharedMesh;
|
||
var lightOffset = lRender.lightmapIndex - rRender.lightmapIndex;
|
||
if (lightOffset === 0) {
|
||
var receiveShadowOffset = (lRender.receiveShadow ? 1 : 0) - (rRender.receiveShadow ? 1 : 0);
|
||
if (receiveShadowOffset === 0) {
|
||
var materialOffset = (lRender.sharedMaterial && rRender.sharedMaterial) ? lRender.sharedMaterial.id - rRender.sharedMaterial.id : 0;
|
||
if (materialOffset === 0) {
|
||
var verDec = leftGeo._vertexBuffer.vertexDeclaration.id - rightGeo._vertexBuffer.vertexDeclaration.id;
|
||
if (verDec === 0) {
|
||
return rightGeo._indexBuffer.indexCount - leftGeo._indexBuffer.indexCount;
|
||
}
|
||
else {
|
||
return verDec;
|
||
}
|
||
}
|
||
else {
|
||
return materialOffset;
|
||
}
|
||
}
|
||
else {
|
||
return receiveShadowOffset;
|
||
}
|
||
}
|
||
else {
|
||
return lightOffset;
|
||
}
|
||
}
|
||
_getBatchRenderElementFromPool() {
|
||
var renderElement = this._batchRenderElementPool[this._batchRenderElementPoolIndex++];
|
||
if (!renderElement) {
|
||
renderElement = new SubMeshRenderElement();
|
||
this._batchRenderElementPool[this._batchRenderElementPoolIndex - 1] = renderElement;
|
||
renderElement.staticBatchElementList = new SingletonList();
|
||
}
|
||
return renderElement;
|
||
}
|
||
_getStaticBatch(staticBatches, rootOwner, number) {
|
||
var subMeshStaticBatch = staticBatches[number];
|
||
if (!subMeshStaticBatch) {
|
||
subMeshStaticBatch = staticBatches[number] = new SubMeshStaticBatch(rootOwner, MeshRenderStaticBatchManager._verDec);
|
||
this._staticBatches[subMeshStaticBatch._batchID] = subMeshStaticBatch;
|
||
}
|
||
return subMeshStaticBatch;
|
||
}
|
||
_initStaticBatchs(rootOwner) {
|
||
var initBatchSprites = this._initBatchSprites;
|
||
this._quickSort(initBatchSprites, 0, initBatchSprites.length - 1);
|
||
var staticBatches = [];
|
||
var lastCanMerage = false;
|
||
var curStaticBatch;
|
||
var batchNumber = 0;
|
||
for (var i = 0, n = initBatchSprites.length; i < n; i++) {
|
||
var sprite = initBatchSprites[i];
|
||
if (lastCanMerage) {
|
||
if (curStaticBatch.addTest(sprite)) {
|
||
curStaticBatch.add(sprite);
|
||
}
|
||
else {
|
||
lastCanMerage = false;
|
||
batchNumber++;
|
||
}
|
||
}
|
||
else {
|
||
var lastIndex = n - 1;
|
||
if (i !== lastIndex) {
|
||
curStaticBatch = this._getStaticBatch(staticBatches, rootOwner, batchNumber);
|
||
curStaticBatch.add(sprite);
|
||
lastCanMerage = true;
|
||
}
|
||
}
|
||
}
|
||
for (i = 0, n = staticBatches.length; i < n; i++) {
|
||
var staticBatch = staticBatches[i];
|
||
staticBatch && staticBatch.finishInit();
|
||
}
|
||
this._initBatchSprites.length = 0;
|
||
}
|
||
_removeRenderSprite(sprite) {
|
||
var render = sprite._render;
|
||
var staticBatch = render._staticBatch;
|
||
var batchElements = staticBatch._batchElements;
|
||
var index = batchElements.indexOf(sprite);
|
||
if (index !== -1) {
|
||
batchElements.splice(index, 1);
|
||
render._staticBatch = null;
|
||
var renderElements = render._renderElements;
|
||
for (var i = 0, n = renderElements.length; i < n; i++)
|
||
renderElements[i].staticBatch = null;
|
||
}
|
||
if (batchElements.length === 0) {
|
||
delete this._staticBatches[staticBatch._batchID];
|
||
staticBatch.dispose();
|
||
}
|
||
}
|
||
_clear() {
|
||
super._clear();
|
||
this._updateCountMark++;
|
||
}
|
||
_garbageCollection() {
|
||
for (var key in this._staticBatches) {
|
||
var staticBatch = this._staticBatches[key];
|
||
if (staticBatch._batchElements.length === 0) {
|
||
staticBatch.dispose();
|
||
delete this._staticBatches[key];
|
||
}
|
||
}
|
||
}
|
||
getBatchOpaquaMark(lightMapIndex, receiveShadow, materialID, staticBatchID) {
|
||
var receiveShadowIndex = receiveShadow ? 1 : 0;
|
||
var staLightMapMarks = (this._opaqueBatchMarks[lightMapIndex]) || (this._opaqueBatchMarks[lightMapIndex] = []);
|
||
var staReceiveShadowMarks = (staLightMapMarks[receiveShadowIndex]) || (staLightMapMarks[receiveShadowIndex] = []);
|
||
var staMaterialMarks = (staReceiveShadowMarks[materialID]) || (staReceiveShadowMarks[materialID] = []);
|
||
return (staMaterialMarks[staticBatchID]) || (staMaterialMarks[staticBatchID] = new BatchMark);
|
||
}
|
||
}
|
||
MeshRenderStaticBatchManager.instance = new MeshRenderStaticBatchManager();
|
||
|
||
(function (ReflectionProbeMode) {
|
||
ReflectionProbeMode[ReflectionProbeMode["off"] = 0] = "off";
|
||
ReflectionProbeMode[ReflectionProbeMode["simple"] = 1] = "simple";
|
||
})(exports.ReflectionProbeMode || (exports.ReflectionProbeMode = {}));
|
||
class ReflectionProbe extends Sprite3D {
|
||
constructor() {
|
||
super();
|
||
this._boxProjection = false;
|
||
this._size = new Vector3();
|
||
this._offset = new Vector3();
|
||
this._reflectionHDRParams = new Vector4();
|
||
this._reflectionDecodeFormat = Laya.TextureDecodeFormat.Normal;
|
||
this._isScene = false;
|
||
}
|
||
get boxProjection() {
|
||
return this._boxProjection;
|
||
}
|
||
set boxProjection(value) {
|
||
this._boxProjection = value;
|
||
}
|
||
get importance() {
|
||
return this._importance;
|
||
}
|
||
set importance(value) {
|
||
this._importance = value;
|
||
}
|
||
get intensity() {
|
||
return this._intensity;
|
||
}
|
||
set intensity(value) {
|
||
value = Math.max(Math.min(value, 1.0), 0.0);
|
||
this._reflectionHDRParams.x = value;
|
||
if (this._reflectionDecodeFormat == Laya.TextureDecodeFormat.RGBM)
|
||
this._reflectionHDRParams.x *= 5.0;
|
||
this._intensity = value;
|
||
}
|
||
get reflectionTexture() {
|
||
return this._reflectionTexture;
|
||
}
|
||
set reflectionTexture(value) {
|
||
this._reflectionTexture = value;
|
||
this._reflectionTexture._addReference();
|
||
}
|
||
get bounds() {
|
||
return this._bounds;
|
||
}
|
||
set bounds(value) {
|
||
this._bounds = value;
|
||
}
|
||
get boundsMax() {
|
||
return this._bounds.getMax();
|
||
}
|
||
get boundsMin() {
|
||
return this._bounds.getMin();
|
||
}
|
||
get probePosition() {
|
||
return this.transform.position;
|
||
}
|
||
get reflectionHDRParams() {
|
||
return this._reflectionHDRParams;
|
||
}
|
||
set reflectionHDRParams(value) {
|
||
this._reflectionHDRParams = value;
|
||
}
|
||
_parse(data, spriteMap) {
|
||
super._parse(data, spriteMap);
|
||
this._boxProjection = data.boxProjection;
|
||
this._importance = data.importance;
|
||
this._reflectionTexture = Laya.Loader.getRes(data.reflection);
|
||
var position = this.transform.position;
|
||
this._size.fromArray(data.boxSize);
|
||
Vector3.scale(this._size, 0.5, ReflectionProbe.TEMPVECTOR3);
|
||
this._offset.fromArray(data.boxOffset);
|
||
var min = new Vector3();
|
||
var max = new Vector3();
|
||
Vector3.add(position, ReflectionProbe.TEMPVECTOR3, max);
|
||
Vector3.add(max, this._offset, max);
|
||
Vector3.subtract(position, ReflectionProbe.TEMPVECTOR3, min);
|
||
Vector3.add(min, this._offset, min);
|
||
this._reflectionDecodeFormat = data.reflectionDecodingFormat;
|
||
this.intensity = data.intensity;
|
||
if (!this._bounds)
|
||
this.bounds = new Bounds(min, max);
|
||
else {
|
||
this._bounds.setMin(min);
|
||
this._bounds.setMax(max);
|
||
}
|
||
}
|
||
_setIndexInReflectionList(value) {
|
||
this._indexInReflectProbList = value;
|
||
}
|
||
_getIndexInReflectionList() {
|
||
return this._indexInReflectProbList;
|
||
}
|
||
_onActive() {
|
||
super._onActive();
|
||
if (this._reflectionTexture)
|
||
this.scene._reflectionProbeManager.add(this);
|
||
}
|
||
_onInActive() {
|
||
super._onInActive();
|
||
if (this.reflectionTexture)
|
||
this.scene._reflectionProbeManager.remove(this);
|
||
}
|
||
destroy(destroyChild = true) {
|
||
if (this.destroyed)
|
||
return;
|
||
super.destroy(destroyChild);
|
||
this._reflectionTexture && this._reflectionTexture._removeReference();
|
||
this._reflectionTexture = null;
|
||
this._bounds = null;
|
||
}
|
||
_cloneTo(destObject, srcRoot, dstRoot) {
|
||
var dest = destObject;
|
||
dest.bounds = this.bounds;
|
||
dest.boxProjection = this.boxProjection;
|
||
dest.importance = this.importance;
|
||
dest._size = this._size;
|
||
dest._offset = this._offset;
|
||
dest.intensity = this.intensity;
|
||
dest.reflectionHDRParams = this.reflectionHDRParams;
|
||
super._cloneTo(destObject, srcRoot, dstRoot);
|
||
}
|
||
}
|
||
ReflectionProbe.TEMPVECTOR3 = new Vector3();
|
||
ReflectionProbe.defaultTextureHDRDecodeValues = new Vector4(1.0, 1.0, 0.0, 0.0);
|
||
|
||
class BaseRender extends Laya.EventDispatcher {
|
||
constructor(owner) {
|
||
super();
|
||
this._lightmapScaleOffset = new Vector4(1, 1, 0, 0);
|
||
this._indexInList = -1;
|
||
this._indexInCastShadowList = -1;
|
||
this._boundsChange = true;
|
||
this._castShadow = false;
|
||
this._supportOctree = true;
|
||
this._sharedMaterials = [];
|
||
this._renderMark = -1;
|
||
this._indexInOctreeMotionList = -1;
|
||
this._reflectionMode = exports.ReflectionProbeMode.simple;
|
||
this._updateMark = -1;
|
||
this._updateRenderType = -1;
|
||
this._isPartOfStaticBatch = false;
|
||
this._staticBatch = null;
|
||
this._id = ++BaseRender._uniqueIDCounter;
|
||
this._indexInCastShadowList = -1;
|
||
this._bounds = new Bounds(Vector3._ZERO, Vector3._ZERO);
|
||
this._renderElements = [];
|
||
this._owner = owner;
|
||
this._enable = true;
|
||
this._materialsInstance = [];
|
||
this._shaderValues = new ShaderData(null);
|
||
this.lightmapIndex = -1;
|
||
this.receiveShadow = false;
|
||
this.sortingFudge = 0.0;
|
||
(owner) && (this._owner.transform.on(Laya.Event.TRANSFORM_CHANGED, this, this._onWorldMatNeedChange));
|
||
}
|
||
get id() {
|
||
return this._id;
|
||
}
|
||
get lightmapIndex() {
|
||
return this._lightmapIndex;
|
||
}
|
||
set lightmapIndex(value) {
|
||
this._lightmapIndex = value;
|
||
}
|
||
get lightmapScaleOffset() {
|
||
return this._lightmapScaleOffset;
|
||
}
|
||
set lightmapScaleOffset(value) {
|
||
if (!value)
|
||
throw "BaseRender: lightmapScaleOffset can't be null.";
|
||
this._lightmapScaleOffset = value;
|
||
this._shaderValues.setVector(RenderableSprite3D.LIGHTMAPSCALEOFFSET, value);
|
||
}
|
||
get enable() {
|
||
return this._enable;
|
||
}
|
||
set enable(value) {
|
||
this._enable = !!value;
|
||
}
|
||
get material() {
|
||
var material = this._sharedMaterials[0];
|
||
if (material && !this._materialsInstance[0]) {
|
||
var insMat = this._getInstanceMaterial(material, 0);
|
||
var renderElement = this._renderElements[0];
|
||
(renderElement) && (renderElement.material = insMat);
|
||
}
|
||
return this._sharedMaterials[0];
|
||
}
|
||
set material(value) {
|
||
this.sharedMaterial = value;
|
||
this._isSupportReflection();
|
||
}
|
||
get materials() {
|
||
for (var i = 0, n = this._sharedMaterials.length; i < n; i++) {
|
||
if (!this._materialsInstance[i]) {
|
||
var insMat = this._getInstanceMaterial(this._sharedMaterials[i], i);
|
||
var renderElement = this._renderElements[i];
|
||
(renderElement) && (renderElement.material = insMat);
|
||
}
|
||
}
|
||
return this._sharedMaterials.slice();
|
||
}
|
||
set materials(value) {
|
||
this.sharedMaterials = value;
|
||
this._isSupportReflection();
|
||
}
|
||
get sharedMaterial() {
|
||
return this._sharedMaterials[0];
|
||
}
|
||
set sharedMaterial(value) {
|
||
var lastValue = this._sharedMaterials[0];
|
||
if (lastValue !== value) {
|
||
this._sharedMaterials[0] = value;
|
||
this._materialsInstance[0] = false;
|
||
this._changeMaterialReference(lastValue, value);
|
||
var renderElement = this._renderElements[0];
|
||
(renderElement) && (renderElement.material = value);
|
||
}
|
||
this._isSupportReflection();
|
||
}
|
||
get sharedMaterials() {
|
||
return this._sharedMaterials.slice();
|
||
}
|
||
set sharedMaterials(value) {
|
||
var materialsInstance = this._materialsInstance;
|
||
var sharedMats = this._sharedMaterials;
|
||
for (var i = 0, n = sharedMats.length; i < n; i++) {
|
||
var lastMat = sharedMats[i];
|
||
(lastMat) && (lastMat._removeReference());
|
||
}
|
||
if (value) {
|
||
var count = value.length;
|
||
materialsInstance.length = count;
|
||
sharedMats.length = count;
|
||
for (i = 0; i < count; i++) {
|
||
lastMat = sharedMats[i];
|
||
var mat = value[i];
|
||
if (lastMat !== mat) {
|
||
materialsInstance[i] = false;
|
||
var renderElement = this._renderElements[i];
|
||
(renderElement) && (renderElement.material = mat);
|
||
}
|
||
if (mat) {
|
||
mat._addReference();
|
||
}
|
||
sharedMats[i] = mat;
|
||
}
|
||
}
|
||
else {
|
||
throw new Error("BaseRender: shadredMaterials value can't be null.");
|
||
}
|
||
this._isSupportReflection();
|
||
}
|
||
get bounds() {
|
||
if (this._boundsChange) {
|
||
this._calculateBoundingBox();
|
||
this._boundsChange = false;
|
||
}
|
||
return this._bounds;
|
||
}
|
||
set receiveShadow(value) {
|
||
if (this._receiveShadow !== value) {
|
||
this._receiveShadow = value;
|
||
if (value)
|
||
this._shaderValues.addDefine(RenderableSprite3D.SHADERDEFINE_RECEIVE_SHADOW);
|
||
else
|
||
this._shaderValues.removeDefine(RenderableSprite3D.SHADERDEFINE_RECEIVE_SHADOW);
|
||
}
|
||
}
|
||
get receiveShadow() {
|
||
return this._receiveShadow;
|
||
}
|
||
get castShadow() {
|
||
return this._castShadow;
|
||
}
|
||
set castShadow(value) {
|
||
this._castShadow = value;
|
||
}
|
||
get isPartOfStaticBatch() {
|
||
return this._isPartOfStaticBatch;
|
||
}
|
||
get isRender() {
|
||
return this._renderMark == -1 || this._renderMark == (Laya.Stat.loopCount - 1);
|
||
}
|
||
set reflectionMode(value) {
|
||
this._reflectionMode = value;
|
||
}
|
||
get reflectionMode() {
|
||
return this._reflectionMode;
|
||
}
|
||
_getOctreeNode() {
|
||
return this._octreeNode;
|
||
}
|
||
_setOctreeNode(value) {
|
||
if (!value) {
|
||
(this._indexInOctreeMotionList !== -1) && (this._octreeNode._octree.removeMotionObject(this));
|
||
}
|
||
this._octreeNode = value;
|
||
}
|
||
_getIndexInMotionList() {
|
||
return this._indexInOctreeMotionList;
|
||
}
|
||
_setIndexInMotionList(value) {
|
||
this._indexInOctreeMotionList = value;
|
||
}
|
||
_changeMaterialReference(lastValue, value) {
|
||
(lastValue) && (lastValue._removeReference());
|
||
value._addReference();
|
||
}
|
||
_getInstanceMaterial(material, index) {
|
||
var insMat = material.clone();
|
||
insMat.name = insMat.name + "(Instance)";
|
||
this._materialsInstance[index] = true;
|
||
this._changeMaterialReference(this._sharedMaterials[index], insMat);
|
||
this._sharedMaterials[index] = insMat;
|
||
return insMat;
|
||
}
|
||
_isSupportReflection() {
|
||
this._surportReflectionProbe = false;
|
||
var sharedMats = this._sharedMaterials;
|
||
for (var i = 0, n = sharedMats.length; i < n; i++) {
|
||
var mat = sharedMats[i];
|
||
this._surportReflectionProbe = (this._surportReflectionProbe || (mat && mat._shader._supportReflectionProbe));
|
||
}
|
||
}
|
||
_addReflectionProbeUpdate() {
|
||
if (this._surportReflectionProbe && this._reflectionMode == 1) {
|
||
this._scene && this._scene._reflectionProbeManager.addMotionObject(this);
|
||
}
|
||
}
|
||
_applyLightMapParams() {
|
||
var lightMaps = this._scene.lightmaps;
|
||
var shaderValues = this._shaderValues;
|
||
var lightmapIndex = this._lightmapIndex;
|
||
if (lightmapIndex >= 0 && lightmapIndex < lightMaps.length) {
|
||
var lightMap = lightMaps[lightmapIndex];
|
||
shaderValues.setTexture(RenderableSprite3D.LIGHTMAP, lightMap.lightmapColor);
|
||
shaderValues.addDefine(RenderableSprite3D.SAHDERDEFINE_LIGHTMAP);
|
||
if (lightMap.lightmapDirection) {
|
||
shaderValues.setTexture(RenderableSprite3D.LIGHTMAP_DIRECTION, lightMap.lightmapDirection);
|
||
shaderValues.addDefine(RenderableSprite3D.SHADERDEFINE_LIGHTMAP_DIRECTIONAL);
|
||
}
|
||
else {
|
||
shaderValues.removeDefine(RenderableSprite3D.SHADERDEFINE_LIGHTMAP_DIRECTIONAL);
|
||
}
|
||
}
|
||
else {
|
||
shaderValues.removeDefine(RenderableSprite3D.SAHDERDEFINE_LIGHTMAP);
|
||
shaderValues.removeDefine(RenderableSprite3D.SHADERDEFINE_LIGHTMAP_DIRECTIONAL);
|
||
}
|
||
}
|
||
_onWorldMatNeedChange(flag) {
|
||
this._boundsChange = true;
|
||
if (this._octreeNode) {
|
||
flag &= Transform3D.TRANSFORM_WORLDPOSITION | Transform3D.TRANSFORM_WORLDQUATERNION | Transform3D.TRANSFORM_WORLDSCALE;
|
||
if (flag) {
|
||
if (this._indexInOctreeMotionList === -1)
|
||
this._octreeNode._octree.addMotionObject(this);
|
||
}
|
||
}
|
||
this._addReflectionProbeUpdate();
|
||
}
|
||
_calculateBoundingBox() {
|
||
throw ("BaseRender: must override it.");
|
||
}
|
||
_getIndexInList() {
|
||
return this._indexInList;
|
||
}
|
||
_setIndexInList(index) {
|
||
this._indexInList = index;
|
||
}
|
||
_setBelongScene(scene) {
|
||
this._scene = scene;
|
||
}
|
||
_setUnBelongScene() {
|
||
this._scene = null;
|
||
}
|
||
_needRender(boundFrustum, context) {
|
||
return true;
|
||
}
|
||
_OctreeNoRender() {
|
||
}
|
||
_renderUpdate(context, transform) {
|
||
}
|
||
_renderUpdateWithCamera(context, transform) {
|
||
}
|
||
_revertBatchRenderUpdate(context) {
|
||
}
|
||
_destroy() {
|
||
(this._indexInOctreeMotionList !== -1) && (this._octreeNode._octree.removeMotionObject(this));
|
||
this.offAll();
|
||
var i = 0, n = 0;
|
||
for (i = 0, n = this._renderElements.length; i < n; i++)
|
||
this._renderElements[i].destroy();
|
||
for (i = 0, n = this._sharedMaterials.length; i < n; i++)
|
||
(this._sharedMaterials[i].destroyed) || (this._sharedMaterials[i]._removeReference());
|
||
this._renderElements = null;
|
||
this._owner = null;
|
||
this._sharedMaterials = null;
|
||
this._bounds = null;
|
||
this._lightmapScaleOffset = null;
|
||
this._scene = null;
|
||
}
|
||
markAsUnStatic() {
|
||
if (this._isPartOfStaticBatch) {
|
||
MeshRenderStaticBatchManager.instance._removeRenderSprite(this._owner);
|
||
this._isPartOfStaticBatch = false;
|
||
}
|
||
}
|
||
}
|
||
BaseRender._tempBoundBoxCorners = [new Vector3(), new Vector3(), new Vector3(), new Vector3(), new Vector3(), new Vector3(), new Vector3(), new Vector3()];
|
||
BaseRender._uniqueIDCounter = 0;
|
||
BaseRender._defaultLightmapScaleOffset = new Vector4(1.0, 1.0, 0.0, 0.0);
|
||
|
||
class PixelLineRenderer extends BaseRender {
|
||
constructor(owner) {
|
||
super(owner);
|
||
this._projectionViewWorldMatrix = new Matrix4x4();
|
||
}
|
||
_calculateBoundingBox() {
|
||
var worldMat = this._owner.transform.worldMatrix;
|
||
var lineFilter = this._owner._geometryFilter;
|
||
lineFilter._reCalculateBound();
|
||
lineFilter._bounds._tranform(worldMat, this._bounds);
|
||
}
|
||
_renderUpdateWithCamera(context, transform) {
|
||
var projectionView = context.projectionViewMatrix;
|
||
var sv = this._shaderValues;
|
||
if (transform) {
|
||
var worldMat = transform.worldMatrix;
|
||
sv.setMatrix4x4(Sprite3D.WORLDMATRIX, worldMat);
|
||
Matrix4x4.multiply(projectionView, worldMat, this._projectionViewWorldMatrix);
|
||
sv.setMatrix4x4(Sprite3D.MVPMATRIX, this._projectionViewWorldMatrix);
|
||
}
|
||
else {
|
||
sv.setMatrix4x4(Sprite3D.WORLDMATRIX, Matrix4x4.DEFAULT);
|
||
sv.setMatrix4x4(Sprite3D.MVPMATRIX, projectionView);
|
||
}
|
||
}
|
||
}
|
||
|
||
class PixelLineSprite3D extends RenderableSprite3D {
|
||
constructor(maxCount = 2, name = null) {
|
||
super(name);
|
||
this._isRenderActive = false;
|
||
this._isInRenders = false;
|
||
this._geometryFilter = new PixelLineFilter(this, maxCount);
|
||
this._render = new PixelLineRenderer(this);
|
||
this._changeRenderObjects(0, PixelLineMaterial.defaultMaterial);
|
||
}
|
||
get maxLineCount() {
|
||
return this._geometryFilter._maxLineCount;
|
||
}
|
||
set maxLineCount(value) {
|
||
this._geometryFilter._resizeLineData(value);
|
||
this._geometryFilter._lineCount = Math.min(this._geometryFilter._lineCount, value);
|
||
}
|
||
get lineCount() {
|
||
return this._geometryFilter._lineCount;
|
||
}
|
||
set lineCount(value) {
|
||
if (value > this.maxLineCount)
|
||
throw "PixelLineSprite3D: lineCount can't large than maxLineCount";
|
||
else
|
||
this._geometryFilter._lineCount = value;
|
||
}
|
||
get pixelLineRenderer() {
|
||
return this._render;
|
||
}
|
||
_onInActive() {
|
||
Laya.Stat.spriteCount--;
|
||
if (this._geometryFilter._lineCount != 0 && this._isRenderActive) {
|
||
this._scene._removeRenderObject(this._render);
|
||
this._isInRenders = false;
|
||
}
|
||
this._isRenderActive = false;
|
||
}
|
||
_onActive() {
|
||
Laya.Stat.spriteCount++;
|
||
this._isRenderActive = true;
|
||
if (this._geometryFilter._lineCount != 0) {
|
||
this._scene._addRenderObject(this._render);
|
||
this._isInRenders = true;
|
||
}
|
||
}
|
||
_changeRenderObjects(index, material) {
|
||
var renderObjects = this._render._renderElements;
|
||
(material) || (material = PixelLineMaterial.defaultMaterial);
|
||
var renderElement = renderObjects[index];
|
||
(renderElement) || (renderElement = renderObjects[index] = new RenderElement());
|
||
renderElement.setTransform(this._transform);
|
||
renderElement.setGeometry(this._geometryFilter);
|
||
renderElement.render = this._render;
|
||
renderElement.material = material;
|
||
}
|
||
addLine(startPosition, endPosition, startColor, endColor) {
|
||
if (this._geometryFilter._lineCount !== this._geometryFilter._maxLineCount)
|
||
this._geometryFilter._updateLineData(this._geometryFilter._lineCount++, startPosition, endPosition, startColor, endColor);
|
||
else
|
||
throw "PixelLineSprite3D: lineCount has equal with maxLineCount.";
|
||
if (this._isRenderActive && !this._isInRenders && this._geometryFilter._lineCount > 0) {
|
||
this._scene._addRenderObject(this._render);
|
||
this._isInRenders = true;
|
||
}
|
||
}
|
||
addLines(lines) {
|
||
var lineCount = this._geometryFilter._lineCount;
|
||
var addCount = lines.length;
|
||
if (lineCount + addCount > this._geometryFilter._maxLineCount) {
|
||
throw "PixelLineSprite3D: lineCount plus lines count must less than maxLineCount.";
|
||
}
|
||
else {
|
||
this._geometryFilter._updateLineDatas(lineCount, lines);
|
||
this._geometryFilter._lineCount += addCount;
|
||
}
|
||
if (this._isRenderActive && !this._isInRenders && this._geometryFilter._lineCount > 0) {
|
||
this._scene._addRenderObject(this._render);
|
||
this._isInRenders = true;
|
||
}
|
||
}
|
||
removeLine(index) {
|
||
if (index < this._geometryFilter._lineCount)
|
||
this._geometryFilter._removeLineData(index);
|
||
else
|
||
throw "PixelLineSprite3D: index must less than lineCount.";
|
||
if (this._isRenderActive && this._isInRenders && this._geometryFilter._lineCount == 0) {
|
||
this._scene._removeRenderObject(this._render);
|
||
this._isInRenders = false;
|
||
}
|
||
}
|
||
setLine(index, startPosition, endPosition, startColor, endColor) {
|
||
if (index < this._geometryFilter._lineCount)
|
||
this._geometryFilter._updateLineData(index, startPosition, endPosition, startColor, endColor);
|
||
else
|
||
throw "PixelLineSprite3D: index must less than lineCount.";
|
||
}
|
||
getLine(index, out) {
|
||
if (index < this.lineCount)
|
||
this._geometryFilter._getLineData(index, out);
|
||
else
|
||
throw "PixelLineSprite3D: index must less than lineCount.";
|
||
}
|
||
clear() {
|
||
this._geometryFilter._lineCount = 0;
|
||
if (this._isRenderActive && this._isInRenders) {
|
||
this._scene._removeRenderObject(this._render);
|
||
this._isInRenders = false;
|
||
}
|
||
}
|
||
_create() {
|
||
return new PixelLineSprite3D();
|
||
}
|
||
}
|
||
|
||
class RenderQueue {
|
||
constructor(isTransparent = false) {
|
||
this.isTransparent = false;
|
||
this.elements = new SingletonList();
|
||
this.lastTransparentRenderElement = null;
|
||
this.lastTransparentBatched = false;
|
||
this.isTransparent = isTransparent;
|
||
}
|
||
_compare(left, right) {
|
||
var renderQueue = left.material.renderQueue - right.material.renderQueue;
|
||
if (renderQueue === 0) {
|
||
var sort = this.isTransparent ? right.render._distanceForSort - left.render._distanceForSort : left.render._distanceForSort - right.render._distanceForSort;
|
||
return sort + right.render.sortingFudge - left.render.sortingFudge;
|
||
}
|
||
else {
|
||
return renderQueue;
|
||
}
|
||
}
|
||
_partitionRenderObject(left, right) {
|
||
var elements = this.elements.elements;
|
||
var pivot = elements[Math.floor((right + left) / 2)];
|
||
while (left <= right) {
|
||
while (this._compare(elements[left], pivot) < 0)
|
||
left++;
|
||
while (this._compare(elements[right], pivot) > 0)
|
||
right--;
|
||
if (left < right) {
|
||
var temp = elements[left];
|
||
elements[left] = elements[right];
|
||
elements[right] = temp;
|
||
left++;
|
||
right--;
|
||
}
|
||
else if (left === right) {
|
||
left++;
|
||
break;
|
||
}
|
||
}
|
||
return left;
|
||
}
|
||
_quickSort(left, right) {
|
||
if (this.elements.length > 1) {
|
||
var index = this._partitionRenderObject(left, right);
|
||
var leftIndex = index - 1;
|
||
if (left < leftIndex)
|
||
this._quickSort(left, leftIndex);
|
||
if (index < right)
|
||
this._quickSort(index, right);
|
||
}
|
||
}
|
||
_render(context) {
|
||
var elements = this.elements.elements;
|
||
for (var i = 0, n = this.elements.length; i < n; i++)
|
||
elements[i]._render(context);
|
||
}
|
||
clear() {
|
||
this.elements.length = 0;
|
||
this.lastTransparentRenderElement = null;
|
||
this.lastTransparentBatched = false;
|
||
}
|
||
}
|
||
|
||
class BoundsOctreeNode {
|
||
constructor(octree, parent, baseLength, center) {
|
||
this._bounds = new BoundBox(new Vector3(), new Vector3());
|
||
this._objects = [];
|
||
this._isContaion = false;
|
||
this.center = new Vector3();
|
||
this.baseLength = 0.0;
|
||
this._setValues(octree, parent, baseLength, center);
|
||
}
|
||
static _encapsulates(outerBound, innerBound) {
|
||
return CollisionUtils.boxContainsBox(outerBound, innerBound) == ContainmentType.Contains;
|
||
}
|
||
_setValues(octree, parent, baseLength, center) {
|
||
this._octree = octree;
|
||
this._parent = parent;
|
||
this.baseLength = baseLength;
|
||
center.cloneTo(this.center);
|
||
var min = this._bounds.min;
|
||
var max = this._bounds.max;
|
||
var halfSize = (octree._looseness * baseLength) / 2;
|
||
min.setValue(center.x - halfSize, center.y - halfSize, center.z - halfSize);
|
||
max.setValue(center.x + halfSize, center.y + halfSize, center.z + halfSize);
|
||
}
|
||
_getChildBound(index) {
|
||
if (this._children != null && this._children[index]) {
|
||
return this._children[index]._bounds;
|
||
}
|
||
else {
|
||
var quarter = this.baseLength / 4;
|
||
var halfChildSize = ((this.baseLength / 2) * this._octree._looseness) / 2;
|
||
var bounds = BoundsOctreeNode._tempBoundBox;
|
||
var min = bounds.min;
|
||
var max = bounds.max;
|
||
switch (index) {
|
||
case 0:
|
||
min.x = this.center.x - quarter - halfChildSize;
|
||
min.y = this.center.y + quarter - halfChildSize;
|
||
min.z = this.center.z - quarter - halfChildSize;
|
||
max.x = this.center.x - quarter + halfChildSize;
|
||
max.y = this.center.y + quarter + halfChildSize;
|
||
max.z = this.center.z - quarter + halfChildSize;
|
||
break;
|
||
case 1:
|
||
min.x = this.center.x + quarter - halfChildSize;
|
||
min.y = this.center.y + quarter - halfChildSize;
|
||
min.z = this.center.z - quarter - halfChildSize;
|
||
max.x = this.center.x + quarter + halfChildSize;
|
||
max.y = this.center.y + quarter + halfChildSize;
|
||
max.z = this.center.z - quarter + halfChildSize;
|
||
break;
|
||
case 2:
|
||
min.x = this.center.x - quarter - halfChildSize;
|
||
min.y = this.center.y + quarter - halfChildSize;
|
||
min.z = this.center.z + quarter - halfChildSize;
|
||
max.x = this.center.x - quarter + halfChildSize;
|
||
max.y = this.center.y + quarter + halfChildSize;
|
||
max.z = this.center.z + quarter + halfChildSize;
|
||
break;
|
||
case 3:
|
||
min.x = this.center.x + quarter - halfChildSize;
|
||
min.y = this.center.y + quarter - halfChildSize;
|
||
min.z = this.center.z + quarter - halfChildSize;
|
||
max.x = this.center.x + quarter + halfChildSize;
|
||
max.y = this.center.y + quarter + halfChildSize;
|
||
max.z = this.center.z + quarter + halfChildSize;
|
||
break;
|
||
case 4:
|
||
min.x = this.center.x - quarter - halfChildSize;
|
||
min.y = this.center.y - quarter - halfChildSize;
|
||
min.z = this.center.z - quarter - halfChildSize;
|
||
max.x = this.center.x - quarter + halfChildSize;
|
||
max.y = this.center.y - quarter + halfChildSize;
|
||
max.z = this.center.z - quarter + halfChildSize;
|
||
break;
|
||
case 5:
|
||
min.x = this.center.x + quarter - halfChildSize;
|
||
min.y = this.center.y - quarter - halfChildSize;
|
||
min.z = this.center.z - quarter - halfChildSize;
|
||
max.x = this.center.x + quarter + halfChildSize;
|
||
max.y = this.center.y - quarter + halfChildSize;
|
||
max.z = this.center.z - quarter + halfChildSize;
|
||
break;
|
||
case 6:
|
||
min.x = this.center.x - quarter - halfChildSize;
|
||
min.y = this.center.y - quarter - halfChildSize;
|
||
min.z = this.center.z + quarter - halfChildSize;
|
||
max.x = this.center.x - quarter + halfChildSize;
|
||
max.y = this.center.y - quarter + halfChildSize;
|
||
max.z = this.center.z + quarter + halfChildSize;
|
||
break;
|
||
case 7:
|
||
min.x = this.center.x + quarter - halfChildSize;
|
||
min.y = this.center.y - quarter - halfChildSize;
|
||
min.z = this.center.z + quarter - halfChildSize;
|
||
max.x = this.center.x + quarter + halfChildSize;
|
||
max.y = this.center.y - quarter + halfChildSize;
|
||
max.z = this.center.z + quarter + halfChildSize;
|
||
break;
|
||
}
|
||
return bounds;
|
||
}
|
||
}
|
||
_getChildCenter(index) {
|
||
if (this._children != null) {
|
||
return this._children[index].center;
|
||
}
|
||
else {
|
||
var quarter = this.baseLength / 4;
|
||
var childCenter = BoundsOctreeNode._tempVector30;
|
||
switch (index) {
|
||
case 0:
|
||
childCenter.x = this.center.x - quarter;
|
||
childCenter.y = this.center.y + quarter;
|
||
childCenter.z = this.center.z - quarter;
|
||
break;
|
||
case 1:
|
||
childCenter.x = this.center.x + quarter;
|
||
childCenter.y = this.center.y + quarter;
|
||
childCenter.z = this.center.z - quarter;
|
||
break;
|
||
case 2:
|
||
childCenter.x = this.center.x - quarter;
|
||
childCenter.y = this.center.y + quarter;
|
||
childCenter.z = this.center.z + quarter;
|
||
break;
|
||
case 3:
|
||
childCenter.x = this.center.x + quarter;
|
||
childCenter.y = this.center.y + quarter;
|
||
childCenter.z = this.center.z + quarter;
|
||
break;
|
||
case 4:
|
||
childCenter.x = this.center.x - quarter;
|
||
childCenter.y = this.center.y - quarter;
|
||
childCenter.z = this.center.z - quarter;
|
||
break;
|
||
case 5:
|
||
childCenter.x = this.center.x + quarter;
|
||
childCenter.y = this.center.y - quarter;
|
||
childCenter.z = this.center.z - quarter;
|
||
break;
|
||
case 6:
|
||
childCenter.x = this.center.x - quarter;
|
||
childCenter.y = this.center.y - quarter;
|
||
childCenter.z = this.center.z + quarter;
|
||
break;
|
||
case 7:
|
||
childCenter.x = this.center.x + quarter;
|
||
childCenter.y = this.center.y - quarter;
|
||
childCenter.z = this.center.z + quarter;
|
||
break;
|
||
}
|
||
return childCenter;
|
||
}
|
||
}
|
||
_getChild(index) {
|
||
var quarter = this.baseLength / 4;
|
||
this._children || (this._children = []);
|
||
switch (index) {
|
||
case 0:
|
||
return this._children[0] || (this._children[0] = new BoundsOctreeNode(this._octree, this, this.baseLength / 2, new Vector3(this.center.x + -quarter, this.center.y + quarter, this.center.z - quarter)));
|
||
case 1:
|
||
return this._children[1] || (this._children[1] = new BoundsOctreeNode(this._octree, this, this.baseLength / 2, new Vector3(this.center.x + quarter, this.center.y + quarter, this.center.z - quarter)));
|
||
case 2:
|
||
return this._children[2] || (this._children[2] = new BoundsOctreeNode(this._octree, this, this.baseLength / 2, new Vector3(this.center.x - quarter, this.center.y + quarter, this.center.z + quarter)));
|
||
case 3:
|
||
return this._children[3] || (this._children[3] = new BoundsOctreeNode(this._octree, this, this.baseLength / 2, new Vector3(this.center.x + quarter, this.center.y + quarter, this.center.z + quarter)));
|
||
case 4:
|
||
return this._children[4] || (this._children[4] = new BoundsOctreeNode(this._octree, this, this.baseLength / 2, new Vector3(this.center.x - quarter, this.center.y - quarter, this.center.z - quarter)));
|
||
case 5:
|
||
return this._children[5] || (this._children[5] = new BoundsOctreeNode(this._octree, this, this.baseLength / 2, new Vector3(this.center.x + quarter, this.center.y - quarter, this.center.z - quarter)));
|
||
case 6:
|
||
return this._children[6] || (this._children[6] = new BoundsOctreeNode(this._octree, this, this.baseLength / 2, new Vector3(this.center.x - quarter, this.center.y - quarter, this.center.z + quarter)));
|
||
case 7:
|
||
return this._children[7] || (this._children[7] = new BoundsOctreeNode(this._octree, this, this.baseLength / 2, new Vector3(this.center.x + quarter, this.center.y - quarter, this.center.z + quarter)));
|
||
default:
|
||
throw "BoundsOctreeNode: unknown index.";
|
||
}
|
||
}
|
||
_shouldMerge() {
|
||
var objectCount = this._objects.length;
|
||
for (var i = 0; i < 8; i++) {
|
||
var child = this._children[i];
|
||
if (child) {
|
||
if (child._children != null)
|
||
return false;
|
||
objectCount += child._objects.length;
|
||
}
|
||
}
|
||
return objectCount <= BoundsOctreeNode._NUM_OBJECTS_ALLOWED;
|
||
}
|
||
_mergeChildren() {
|
||
for (var i = 0; i < 8; i++) {
|
||
var child = this._children[i];
|
||
if (child) {
|
||
child._parent = null;
|
||
var childObjects = child._objects;
|
||
for (var j = childObjects.length - 1; j >= 0; j--) {
|
||
var childObject = childObjects[j];
|
||
this._objects.push(childObject);
|
||
childObject._setOctreeNode(this);
|
||
}
|
||
}
|
||
}
|
||
this._children = null;
|
||
}
|
||
_merge() {
|
||
if (this._children === null) {
|
||
var parent = this._parent;
|
||
if (parent && parent._shouldMerge()) {
|
||
parent._mergeChildren();
|
||
parent._merge();
|
||
}
|
||
}
|
||
}
|
||
_checkAddNode(object) {
|
||
if (this._children == null) {
|
||
if (this._objects.length < BoundsOctreeNode._NUM_OBJECTS_ALLOWED || (this.baseLength / 2) < this._octree._minSize) {
|
||
return this;
|
||
}
|
||
for (var i = this._objects.length - 1; i >= 0; i--) {
|
||
var existObject = this._objects[i];
|
||
var fitChildIndex = this._bestFitChild(existObject.bounds.getCenter());
|
||
if (BoundsOctreeNode._encapsulates(this._getChildBound(fitChildIndex), existObject.bounds._getBoundBox())) {
|
||
this._objects.splice(this._objects.indexOf(existObject), 1);
|
||
this._getChild(fitChildIndex)._add(existObject);
|
||
}
|
||
}
|
||
}
|
||
var newFitChildIndex = this._bestFitChild(object.bounds.getCenter());
|
||
if (BoundsOctreeNode._encapsulates(this._getChildBound(newFitChildIndex), object.bounds._getBoundBox()))
|
||
return this._getChild(newFitChildIndex)._checkAddNode(object);
|
||
else
|
||
return this;
|
||
}
|
||
_add(object) {
|
||
var addNode = this._checkAddNode(object);
|
||
addNode._objects.push(object);
|
||
object._setOctreeNode(addNode);
|
||
}
|
||
_remove(object) {
|
||
var index = this._objects.indexOf(object);
|
||
this._objects.splice(index, 1);
|
||
object._setOctreeNode(null);
|
||
this._merge();
|
||
}
|
||
_addUp(object) {
|
||
if ((CollisionUtils.boxContainsBox(this._bounds, object.bounds._getBoundBox()) === ContainmentType.Contains)) {
|
||
this._add(object);
|
||
return true;
|
||
}
|
||
else {
|
||
if (this._parent)
|
||
return this._parent._addUp(object);
|
||
else
|
||
return false;
|
||
}
|
||
}
|
||
_getCollidingWithFrustum(cameraCullInfo, context, testVisible, customShader, replacementTag, isShadowCasterCull) {
|
||
var frustum = cameraCullInfo.boundFrustum;
|
||
var camPos = cameraCullInfo.position;
|
||
var cullMask = cameraCullInfo.cullingMask;
|
||
if (testVisible) {
|
||
var type = frustum.containsBoundBox(this._bounds);
|
||
Laya.Stat.octreeNodeCulling++;
|
||
if (type === ContainmentType.Disjoint) {
|
||
for (var i = 0, n = this._objects.length; i < n; i++) {
|
||
this._objects[i]._OctreeNoRender();
|
||
}
|
||
return;
|
||
}
|
||
testVisible = (type === ContainmentType.Intersects);
|
||
}
|
||
this._isContaion = !testVisible;
|
||
var scene = context.scene;
|
||
var loopCount = Laya.Stat.loopCount;
|
||
for (var i = 0, n = this._objects.length; i < n; i++) {
|
||
var render = this._objects[i];
|
||
var canPass;
|
||
if (isShadowCasterCull)
|
||
canPass = render._castShadow && render._enable;
|
||
else
|
||
canPass = (((Math.pow(2, render._owner._layer) & cullMask) != 0)) && render._enable;
|
||
if (canPass) {
|
||
if (testVisible) {
|
||
Laya.Stat.frustumCulling++;
|
||
if (!render._needRender(frustum, context))
|
||
continue;
|
||
}
|
||
render._renderMark = loopCount;
|
||
render._distanceForSort = Vector3.distance(render.bounds.getCenter(), camPos);
|
||
var elements = render._renderElements;
|
||
for (var j = 0, m = elements.length; j < m; j++) {
|
||
var element = elements[j];
|
||
element._update(scene, context, customShader, replacementTag);
|
||
}
|
||
}
|
||
}
|
||
if (this._children != null) {
|
||
for (i = 0; i < 8; i++) {
|
||
var child = this._children[i];
|
||
child && child._getCollidingWithFrustum(cameraCullInfo, context, testVisible, customShader, replacementTag, isShadowCasterCull);
|
||
}
|
||
}
|
||
}
|
||
_getCollidingWithCastShadowFrustum(cullInfo, context) {
|
||
var cullPlaneCount = cullInfo.cullPlaneCount;
|
||
var cullPlanes = cullInfo.cullPlanes;
|
||
var min = this._bounds.min;
|
||
var max = this._bounds.max;
|
||
var minX = min.x;
|
||
var minY = min.y;
|
||
var minZ = min.z;
|
||
var maxX = max.x;
|
||
var maxY = max.y;
|
||
var maxZ = max.z;
|
||
var pass = true;
|
||
for (var j = 0; j < cullPlaneCount; j++) {
|
||
var plane = cullPlanes[j];
|
||
var normal = plane.normal;
|
||
if (plane.distance + (normal.x * (normal.x < 0.0 ? minX : maxX)) + (normal.y * (normal.y < 0.0 ? minY : maxY)) + (normal.z * (normal.z < 0.0 ? minZ : maxZ)) < 0.0) {
|
||
pass = false;
|
||
break;
|
||
}
|
||
}
|
||
if (!pass)
|
||
return;
|
||
var scene = context.scene;
|
||
var loopCount = Laya.Stat.loopCount;
|
||
for (var i = 0, n = this._objects.length; i < n; i++) {
|
||
var render = this._objects[i];
|
||
var canPass;
|
||
let pass = true;
|
||
canPass = render._castShadow && render._enable;
|
||
if (canPass) {
|
||
for (var j = 0; j < cullPlaneCount; j++) {
|
||
var plane = cullPlanes[j];
|
||
var normal = plane.normal;
|
||
if (plane.distance + (normal.x * (normal.x < 0.0 ? minX : maxX)) + (normal.y * (normal.y < 0.0 ? minY : maxY)) + (normal.z * (normal.z < 0.0 ? minZ : maxZ)) < 0.0) {
|
||
pass = false;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (!pass || !canPass)
|
||
continue;
|
||
render._renderMark = loopCount;
|
||
render._distanceForSort = Vector3.distance(render.bounds.getCenter(), cullInfo.position);
|
||
var elements = render._renderElements;
|
||
for (var j = 0, m = elements.length; j < m; j++) {
|
||
var element = elements[j];
|
||
element._update(scene, context, null, null);
|
||
}
|
||
}
|
||
if (this._children != null) {
|
||
for (i = 0; i < 8; i++) {
|
||
var child = this._children[i];
|
||
child && child._getCollidingWithCastShadowFrustum(cullInfo, context);
|
||
}
|
||
}
|
||
}
|
||
_getCollidingWithBoundBox(checkBound, testVisible, result) {
|
||
if (testVisible) {
|
||
var type = CollisionUtils.boxContainsBox(this._bounds, checkBound);
|
||
if (type === ContainmentType.Disjoint)
|
||
return;
|
||
testVisible = (type === ContainmentType.Intersects);
|
||
}
|
||
if (testVisible) {
|
||
for (var i = 0, n = this._objects.length; i < n; i++) {
|
||
var object = this._objects[i];
|
||
if (CollisionUtils.intersectsBoxAndBox(object.bounds._getBoundBox(), checkBound)) {
|
||
result.push(object);
|
||
}
|
||
}
|
||
}
|
||
if (this._children != null) {
|
||
for (i = 0; i < 8; i++) {
|
||
var child = this._children[i];
|
||
child._getCollidingWithBoundBox(checkBound, testVisible, result);
|
||
}
|
||
}
|
||
}
|
||
_bestFitChild(boundCenter) {
|
||
return (boundCenter.x <= this.center.x ? 0 : 1) + (boundCenter.y >= this.center.y ? 0 : 4) + (boundCenter.z <= this.center.z ? 0 : 2);
|
||
}
|
||
_update(object) {
|
||
if (CollisionUtils.boxContainsBox(this._bounds, object.bounds._getBoundBox()) === ContainmentType.Contains) {
|
||
var addNode = this._checkAddNode(object);
|
||
if (addNode !== object._getOctreeNode()) {
|
||
addNode._objects.push(object);
|
||
object._setOctreeNode(addNode);
|
||
var index = this._objects.indexOf(object);
|
||
this._objects.splice(index, 1);
|
||
this._merge();
|
||
}
|
||
return true;
|
||
}
|
||
else {
|
||
if (this._parent) {
|
||
var sucess = this._parent._addUp(object);
|
||
if (sucess) {
|
||
index = this._objects.indexOf(object);
|
||
this._objects.splice(index, 1);
|
||
this._merge();
|
||
}
|
||
return sucess;
|
||
}
|
||
else {
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
add(object) {
|
||
if (!BoundsOctreeNode._encapsulates(this._bounds, object.bounds._getBoundBox()))
|
||
return false;
|
||
this._add(object);
|
||
return true;
|
||
}
|
||
remove(object) {
|
||
if (object._getOctreeNode() !== this)
|
||
return false;
|
||
this._remove(object);
|
||
return true;
|
||
}
|
||
update(object) {
|
||
if (object._getOctreeNode() !== this)
|
||
return false;
|
||
return this._update(object);
|
||
}
|
||
shrinkIfPossible(minLength) {
|
||
if (this.baseLength < minLength * 2)
|
||
return this;
|
||
var bestFit = -1;
|
||
for (var i = 0, n = this._objects.length; i < n; i++) {
|
||
var object = this._objects[i];
|
||
var newBestFit = this._bestFitChild(object.bounds.getCenter());
|
||
if (i == 0 || newBestFit == bestFit) {
|
||
var childBounds = this._getChildBound(newBestFit);
|
||
if (BoundsOctreeNode._encapsulates(childBounds, object.bounds._getBoundBox()))
|
||
(i == 0) && (bestFit = newBestFit);
|
||
else
|
||
return this;
|
||
}
|
||
else {
|
||
return this;
|
||
}
|
||
}
|
||
if (this._children != null) {
|
||
var childHadContent = false;
|
||
for (i = 0, n = this._children.length; i < n; i++) {
|
||
var child = this._children[i];
|
||
if (child && child.hasAnyObjects()) {
|
||
if (childHadContent)
|
||
return this;
|
||
if (bestFit >= 0 && bestFit != i)
|
||
return this;
|
||
childHadContent = true;
|
||
bestFit = i;
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
if (bestFit != -1) {
|
||
var childCenter = this._getChildCenter(bestFit);
|
||
this._setValues(this._octree, null, this.baseLength / 2, childCenter);
|
||
}
|
||
return this;
|
||
}
|
||
if (bestFit != -1) {
|
||
var newRoot = this._children[bestFit];
|
||
newRoot._parent = null;
|
||
return newRoot;
|
||
}
|
||
else {
|
||
return this;
|
||
}
|
||
}
|
||
hasAnyObjects() {
|
||
if (this._objects.length > 0)
|
||
return true;
|
||
if (this._children != null) {
|
||
for (var i = 0; i < 8; i++) {
|
||
var child = this._children[i];
|
||
if (child && child.hasAnyObjects())
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
getCollidingWithBoundBox(checkBound, result) {
|
||
this._getCollidingWithBoundBox(checkBound, true, result);
|
||
}
|
||
getCollidingWithRay(ray, result, maxDistance = Number.MAX_VALUE) {
|
||
var distance = CollisionUtils.intersectsRayAndBoxRD(ray, this._bounds);
|
||
if (distance == -1 || distance > maxDistance)
|
||
return;
|
||
for (var i = 0, n = this._objects.length; i < n; i++) {
|
||
var object = this._objects[i];
|
||
distance = CollisionUtils.intersectsRayAndBoxRD(ray, object.bounds._getBoundBox());
|
||
if (distance !== -1 && distance <= maxDistance)
|
||
result.push(object);
|
||
}
|
||
if (this._children != null) {
|
||
for (i = 0; i < 8; i++) {
|
||
var child = this._children[i];
|
||
child.getCollidingWithRay(ray, result, maxDistance);
|
||
}
|
||
}
|
||
}
|
||
getCollidingWithFrustum(cameraCullInfo, context, customShader, replacementTag, isShadowCasterCull) {
|
||
this._getCollidingWithFrustum(cameraCullInfo, context, true, customShader, replacementTag, isShadowCasterCull);
|
||
}
|
||
getCollidingWithCastShadowFrustum(cameraCullInfo, contect) {
|
||
this._getCollidingWithCastShadowFrustum(cameraCullInfo, contect);
|
||
}
|
||
isCollidingWithBoundBox(checkBound) {
|
||
if (!(CollisionUtils.intersectsBoxAndBox(this._bounds, checkBound)))
|
||
return false;
|
||
for (var i = 0, n = this._objects.length; i < n; i++) {
|
||
var object = this._objects[i];
|
||
if (CollisionUtils.intersectsBoxAndBox(object.bounds._getBoundBox(), checkBound))
|
||
return true;
|
||
}
|
||
if (this._children != null) {
|
||
for (i = 0; i < 8; i++) {
|
||
var child = this._children[i];
|
||
if (child.isCollidingWithBoundBox(checkBound))
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
isCollidingWithRay(ray, maxDistance = Number.MAX_VALUE) {
|
||
var distance = CollisionUtils.intersectsRayAndBoxRD(ray, this._bounds);
|
||
if (distance == -1 || distance > maxDistance)
|
||
return false;
|
||
for (var i = 0, n = this._objects.length; i < n; i++) {
|
||
var object = this._objects[i];
|
||
distance = CollisionUtils.intersectsRayAndBoxRD(ray, object.bounds._getBoundBox());
|
||
if (distance !== -1 && distance <= maxDistance)
|
||
return true;
|
||
}
|
||
if (this._children != null) {
|
||
for (i = 0; i < 8; i++) {
|
||
var child = this._children[i];
|
||
if (child.isCollidingWithRay(ray, maxDistance))
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
getBound() {
|
||
return this._bounds;
|
||
}
|
||
drawAllBounds(debugLine, currentDepth, maxDepth) {
|
||
if (this._children === null && this._objects.length == 0)
|
||
return;
|
||
currentDepth++;
|
||
var color = BoundsOctreeNode._tempColor0;
|
||
if (this._isContaion) {
|
||
color.r = 0.0;
|
||
color.g = 0.0;
|
||
color.b = 1.0;
|
||
}
|
||
else {
|
||
var tint = maxDepth ? currentDepth / maxDepth : 0;
|
||
color.r = 1.0 - tint;
|
||
color.g = tint;
|
||
color.b = 0.0;
|
||
}
|
||
color.a = 0.3;
|
||
Utils3D._drawBound(debugLine, this._bounds, color);
|
||
if (this._children != null) {
|
||
for (var i = 0; i < 8; i++) {
|
||
var child = this._children[i];
|
||
child && child.drawAllBounds(debugLine, currentDepth, maxDepth);
|
||
}
|
||
}
|
||
}
|
||
drawAllObjects(debugLine, currentDepth, maxDepth) {
|
||
currentDepth++;
|
||
var color = BoundsOctreeNode._tempColor0;
|
||
if (this._isContaion) {
|
||
color.r = 0.0;
|
||
color.g = 0.0;
|
||
color.b = 1.0;
|
||
}
|
||
else {
|
||
var tint = maxDepth ? currentDepth / maxDepth : 0;
|
||
color.r = 1.0 - tint;
|
||
color.g = tint;
|
||
color.b = 0.0;
|
||
}
|
||
color.a = 1.0;
|
||
for (var i = 0, n = this._objects.length; i < n; i++)
|
||
Utils3D._drawBound(debugLine, this._objects[i].bounds._getBoundBox(), color);
|
||
if (this._children != null) {
|
||
for (i = 0; i < 8; i++) {
|
||
var child = this._children[i];
|
||
child && child.drawAllObjects(debugLine, currentDepth, maxDepth);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
BoundsOctreeNode._tempVector30 = new Vector3();
|
||
BoundsOctreeNode._tempColor0 = new Color();
|
||
BoundsOctreeNode._tempBoundBox = new BoundBox(new Vector3(), new Vector3());
|
||
BoundsOctreeNode._NUM_OBJECTS_ALLOWED = 8;
|
||
|
||
class OctreeMotionList extends SingletonList {
|
||
constructor() {
|
||
super();
|
||
}
|
||
add(element) {
|
||
var index = element._getIndexInMotionList();
|
||
if (index !== -1)
|
||
throw "OctreeMotionList:element has in PhysicsUpdateList.";
|
||
this._add(element);
|
||
element._setIndexInMotionList(this.length++);
|
||
}
|
||
remove(element) {
|
||
var index = element._getIndexInMotionList();
|
||
this.length--;
|
||
if (index !== this.length) {
|
||
var end = this.elements[this.length];
|
||
this.elements[index] = end;
|
||
end._setIndexInMotionList(index);
|
||
}
|
||
element._setIndexInMotionList(-1);
|
||
}
|
||
}
|
||
|
||
class BoundsOctree {
|
||
constructor(initialWorldSize, initialWorldPos, minNodeSize, looseness) {
|
||
this._motionObjects = new OctreeMotionList();
|
||
this.count = 0;
|
||
if (minNodeSize > initialWorldSize) {
|
||
console.warn("Minimum node size must be at least as big as the initial world size. Was: " + minNodeSize + " Adjusted to: " + initialWorldSize);
|
||
minNodeSize = initialWorldSize;
|
||
}
|
||
this._initialSize = initialWorldSize;
|
||
this._minSize = minNodeSize;
|
||
this._looseness = Math.min(Math.max(looseness, 1.0), 2.0);
|
||
this._rootNode = new BoundsOctreeNode(this, null, initialWorldSize, initialWorldPos);
|
||
}
|
||
_getMaxDepth(node, depth) {
|
||
depth++;
|
||
var children = node._children;
|
||
if (children != null) {
|
||
var curDepth = depth;
|
||
for (var i = 0, n = children.length; i < n; i++) {
|
||
var child = children[i];
|
||
child && (depth = Math.max(this._getMaxDepth(child, curDepth), depth));
|
||
}
|
||
}
|
||
return depth;
|
||
}
|
||
_grow(growObjectCenter) {
|
||
var xDirection = growObjectCenter.x >= 0 ? 1 : -1;
|
||
var yDirection = growObjectCenter.y >= 0 ? 1 : -1;
|
||
var zDirection = growObjectCenter.z >= 0 ? 1 : -1;
|
||
var oldRoot = this._rootNode;
|
||
var half = this._rootNode.baseLength / 2;
|
||
var newLength = this._rootNode.baseLength * 2;
|
||
var rootCenter = this._rootNode.center;
|
||
var newCenter = new Vector3(rootCenter.x + xDirection * half, rootCenter.y + yDirection * half, rootCenter.z + zDirection * half);
|
||
this._rootNode = new BoundsOctreeNode(this, null, newLength, newCenter);
|
||
if (oldRoot.hasAnyObjects()) {
|
||
var rootPos = this._rootNode._bestFitChild(oldRoot.center);
|
||
var children = [];
|
||
for (var i = 0; i < 8; i++) {
|
||
if (i == rootPos) {
|
||
oldRoot._parent = this._rootNode;
|
||
children[i] = oldRoot;
|
||
}
|
||
}
|
||
this._rootNode._children = children;
|
||
}
|
||
}
|
||
add(object) {
|
||
var count = 0;
|
||
while (!this._rootNode.add(object)) {
|
||
var growCenter = BoundsOctree._tempVector30;
|
||
Vector3.subtract(object.bounds.getCenter(), this._rootNode.center, growCenter);
|
||
this._grow(growCenter);
|
||
if (++count > 20) {
|
||
throw "Aborted Add operation as it seemed to be going on forever (" + (count - 1) + ") attempts at growing the octree.";
|
||
}
|
||
}
|
||
this.count++;
|
||
}
|
||
remove(object) {
|
||
var removed = object._getOctreeNode().remove(object);
|
||
if (removed) {
|
||
this.count--;
|
||
}
|
||
return removed;
|
||
}
|
||
update(object) {
|
||
var count = 0;
|
||
var octreeNode = object._getOctreeNode();
|
||
if (octreeNode) {
|
||
while (!octreeNode._update(object)) {
|
||
var growCenter = BoundsOctree._tempVector30;
|
||
Vector3.subtract(object.bounds.getCenter(), this._rootNode.center, growCenter);
|
||
this._grow(growCenter);
|
||
if (++count > 20) {
|
||
throw "Aborted Add operation as it seemed to be going on forever (" + (count - 1) + ") attempts at growing the octree.";
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
else {
|
||
return false;
|
||
}
|
||
}
|
||
shrinkRootIfPossible() {
|
||
this._rootNode = this._rootNode.shrinkIfPossible(this._initialSize);
|
||
}
|
||
addMotionObject(object) {
|
||
this._motionObjects.add(object);
|
||
}
|
||
removeMotionObject(object) {
|
||
this._motionObjects.remove(object);
|
||
}
|
||
updateMotionObjects() {
|
||
var elements = this._motionObjects.elements;
|
||
for (var i = 0, n = this._motionObjects.length; i < n; i++) {
|
||
var object = elements[i];
|
||
this.update(object);
|
||
object._setIndexInMotionList(-1);
|
||
}
|
||
this._motionObjects.length = 0;
|
||
}
|
||
isCollidingWithBoundBox(checkBounds) {
|
||
return this._rootNode.isCollidingWithBoundBox(checkBounds);
|
||
}
|
||
isCollidingWithRay(ray, maxDistance = Number.MAX_VALUE) {
|
||
return this._rootNode.isCollidingWithRay(ray, maxDistance);
|
||
}
|
||
getCollidingWithBoundBox(checkBound, result) {
|
||
this._rootNode.getCollidingWithBoundBox(checkBound, result);
|
||
}
|
||
getCollidingWithRay(ray, result, maxDistance = Number.MAX_VALUE) {
|
||
this._rootNode.getCollidingWithRay(ray, result, maxDistance);
|
||
}
|
||
getCollidingWithFrustum(cameraCullInfo, context, shader, replacementTag, isShadowCasterCull) {
|
||
this._rootNode.getCollidingWithFrustum(cameraCullInfo, context, shader, replacementTag, isShadowCasterCull);
|
||
}
|
||
getMaxBounds() {
|
||
return this._rootNode.getBound();
|
||
}
|
||
drawAllBounds(pixelLine) {
|
||
var maxDepth = this._getMaxDepth(this._rootNode, -1);
|
||
this._rootNode.drawAllBounds(pixelLine, -1, maxDepth);
|
||
}
|
||
drawAllObjects(pixelLine) {
|
||
var maxDepth = this._getMaxDepth(this._rootNode, -1);
|
||
this._rootNode.drawAllObjects(pixelLine, -1, maxDepth);
|
||
}
|
||
}
|
||
BoundsOctree._tempVector30 = new Vector3();
|
||
|
||
class Lightmap {
|
||
}
|
||
|
||
class BoundSphere {
|
||
constructor(center, radius) {
|
||
this.center = center;
|
||
this.radius = radius;
|
||
}
|
||
toDefault() {
|
||
this.center.toDefault();
|
||
this.radius = 0;
|
||
}
|
||
static createFromSubPoints(points, start, count, out) {
|
||
if (points == null) {
|
||
throw new Error("points");
|
||
}
|
||
if (start < 0 || start >= points.length) {
|
||
throw new Error("start" + start + "Must be in the range [0, " + (points.length - 1) + "]");
|
||
}
|
||
if (count < 0 || (start + count) > points.length) {
|
||
throw new Error("count" + count + "Must be in the range <= " + points.length + "}");
|
||
}
|
||
var upperEnd = start + count;
|
||
var center = BoundSphere._tempVector3;
|
||
center.x = 0;
|
||
center.y = 0;
|
||
center.z = 0;
|
||
for (var i = start; i < upperEnd; ++i) {
|
||
Vector3.add(points[i], center, center);
|
||
}
|
||
var outCenter = out.center;
|
||
Vector3.scale(center, 1 / count, outCenter);
|
||
var radius = 0.0;
|
||
for (i = start; i < upperEnd; ++i) {
|
||
var distance = Vector3.distanceSquared(outCenter, points[i]);
|
||
if (distance > radius)
|
||
radius = distance;
|
||
}
|
||
out.radius = Math.sqrt(radius);
|
||
}
|
||
static createfromPoints(points, out) {
|
||
if (points == null) {
|
||
throw new Error("points");
|
||
}
|
||
BoundSphere.createFromSubPoints(points, 0, points.length, out);
|
||
}
|
||
intersectsRayDistance(ray) {
|
||
return CollisionUtils.intersectsRayAndSphereRD(ray, this);
|
||
}
|
||
intersectsRayPoint(ray, outPoint) {
|
||
return CollisionUtils.intersectsRayAndSphereRP(ray, this, outPoint);
|
||
}
|
||
cloneTo(destObject) {
|
||
var dest = destObject;
|
||
this.center.cloneTo(dest.center);
|
||
dest.radius = this.radius;
|
||
}
|
||
clone() {
|
||
var dest = new BoundSphere(new Vector3(), 0);
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
}
|
||
BoundSphere._tempVector3 = new Vector3();
|
||
|
||
class ShadowSliceData {
|
||
constructor() {
|
||
this.cameraShaderValue = new ShaderData();
|
||
this.position = new Vector3();
|
||
this.viewMatrix = new Matrix4x4();
|
||
this.projectionMatrix = new Matrix4x4();
|
||
this.viewProjectMatrix = new Matrix4x4();
|
||
this.cullPlanes = [new Plane(new Vector3()), new Plane(new Vector3()), new Plane(new Vector3()), new Plane(new Vector3()), new Plane(new Vector3()), new Plane(new Vector3()), new Plane(new Vector3()), new Plane(new Vector3()), new Plane(new Vector3()), new Plane(new Vector3())];
|
||
this.splitBoundSphere = new BoundSphere(new Vector3(), 0.0);
|
||
}
|
||
}
|
||
class ShadowSpotData {
|
||
constructor() {
|
||
this.cameraShaderValue = new ShaderData();
|
||
this.position = new Vector3;
|
||
this.viewMatrix = new Matrix4x4();
|
||
this.projectionMatrix = new Matrix4x4();
|
||
this.viewProjectMatrix = new Matrix4x4();
|
||
this.cameraCullInfo = new CameraCullInfo();
|
||
}
|
||
}
|
||
|
||
(function (ShadowLightType) {
|
||
ShadowLightType[ShadowLightType["DirectionLight"] = 0] = "DirectionLight";
|
||
ShadowLightType[ShadowLightType["SpotLight"] = 1] = "SpotLight";
|
||
ShadowLightType[ShadowLightType["PointLight"] = 2] = "PointLight";
|
||
})(exports.ShadowLightType || (exports.ShadowLightType = {}));
|
||
class ShadowCasterPass {
|
||
constructor() {
|
||
this._shadowBias = new Vector4();
|
||
this._shadowParams = new Vector4();
|
||
this._shadowMapSize = new Vector4();
|
||
this._shadowSpotMapSize = new Vector4();
|
||
this._shadowMatrices = new Float32Array(16 * (ShadowCasterPass._maxCascades));
|
||
this._shadowSpotMatrices = new Matrix4x4();
|
||
this._splitBoundSpheres = new Float32Array(ShadowCasterPass._maxCascades * 4);
|
||
this._cascadeCount = 0;
|
||
this._shadowMapWidth = 0;
|
||
this._shadowMapHeight = 0;
|
||
this._shadowSliceDatas = [new ShadowSliceData(), new ShadowSliceData(), new ShadowSliceData(), new ShadowSliceData()];
|
||
this._shadowSpotData = new ShadowSpotData();
|
||
this._lightUp = new Vector3();
|
||
this._lightSide = new Vector3();
|
||
this._lightForward = new Vector3();
|
||
this._shadowSpotData.cameraCullInfo.boundFrustum = new BoundFrustum(new Matrix4x4());
|
||
}
|
||
_setupShadowCasterShaderValues(context, shaderValues, shadowSliceData, LightParam, shadowparams, shadowBias, lightType) {
|
||
shaderValues.setVector(ShadowCasterPass.SHADOW_BIAS, shadowBias);
|
||
switch (lightType) {
|
||
case exports.LightType.Directional:
|
||
shaderValues.setVector3(ShadowCasterPass.SHADOW_LIGHT_DIRECTION, LightParam);
|
||
break;
|
||
case exports.LightType.Spot:
|
||
shaderValues.setVector(ShadowCasterPass.SHADOW_PARAMS, shadowparams);
|
||
break;
|
||
case exports.LightType.Point:
|
||
break;
|
||
}
|
||
var cameraSV = shadowSliceData.cameraShaderValue;
|
||
cameraSV.setMatrix4x4(BaseCamera.VIEWMATRIX, shadowSliceData.viewMatrix);
|
||
cameraSV.setMatrix4x4(BaseCamera.PROJECTMATRIX, shadowSliceData.projectionMatrix);
|
||
cameraSV.setMatrix4x4(BaseCamera.VIEWPROJECTMATRIX, shadowSliceData.viewProjectMatrix);
|
||
context.viewMatrix = shadowSliceData.viewMatrix;
|
||
context.projectionMatrix = shadowSliceData.projectionMatrix;
|
||
context.projectionViewMatrix = shadowSliceData.viewProjectMatrix;
|
||
}
|
||
_setupShadowReceiverShaderValues(shaderValues) {
|
||
var light = this._light;
|
||
if (light.shadowCascadesMode !== exports.ShadowCascadesMode.NoCascades)
|
||
shaderValues.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_CASCADE);
|
||
else
|
||
shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_CASCADE);
|
||
switch (light.shadowMode) {
|
||
case exports.ShadowMode.Hard:
|
||
shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_SOFT_SHADOW_LOW);
|
||
shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_SOFT_SHADOW_HIGH);
|
||
break;
|
||
case exports.ShadowMode.SoftLow:
|
||
shaderValues.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_SOFT_SHADOW_LOW);
|
||
shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_SOFT_SHADOW_HIGH);
|
||
break;
|
||
case exports.ShadowMode.SoftHigh:
|
||
shaderValues.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_SOFT_SHADOW_HIGH);
|
||
shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_SOFT_SHADOW_LOW);
|
||
break;
|
||
}
|
||
shaderValues.setTexture(ShadowCasterPass.SHADOW_MAP, this._shadowDirectLightMap);
|
||
shaderValues.setBuffer(ShadowCasterPass.SHADOW_MATRICES, this._shadowMatrices);
|
||
shaderValues.setVector(ShadowCasterPass.SHADOW_MAP_SIZE, this._shadowMapSize);
|
||
shaderValues.setVector(ShadowCasterPass.SHADOW_PARAMS, this._shadowParams);
|
||
shaderValues.setBuffer(ShadowCasterPass.SHADOW_SPLIT_SPHERES, this._splitBoundSpheres);
|
||
}
|
||
_setupSpotShadowReceiverShaderValues(shaderValues) {
|
||
var spotLight = this._light;
|
||
switch (spotLight.shadowMode) {
|
||
case exports.ShadowMode.Hard:
|
||
shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_SPOT_SOFT_SHADOW_HIGH);
|
||
shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_SPOT_SOFT_SHADOW_LOW);
|
||
break;
|
||
case exports.ShadowMode.SoftLow:
|
||
shaderValues.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_SPOT_SOFT_SHADOW_LOW);
|
||
shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_SPOT_SOFT_SHADOW_HIGH);
|
||
break;
|
||
case exports.ShadowMode.SoftHigh:
|
||
shaderValues.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_SPOT_SOFT_SHADOW_HIGH);
|
||
shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_SPOT_SOFT_SHADOW_LOW);
|
||
break;
|
||
}
|
||
shaderValues.setTexture(ShadowCasterPass.SHADOW_SPOTMAP, this._shadowSpotLightMap);
|
||
shaderValues.setMatrix4x4(ShadowCasterPass.SHADOW_SPOTMATRICES, this._shadowSpotMatrices);
|
||
shaderValues.setVector(ShadowCasterPass.SHADOW_SPOTMAP_SIZE, this._shadowSpotMapSize);
|
||
shaderValues.setVector(ShadowCasterPass.SHADOW_PARAMS, this._shadowParams);
|
||
}
|
||
update(camera, light, lightType) {
|
||
switch (lightType) {
|
||
case exports.ShadowLightType.DirectionLight:
|
||
this._light = light;
|
||
var lightWorld = ShadowCasterPass._tempMatrix0;
|
||
var lightWorldE = lightWorld.elements;
|
||
var lightUp = this._lightUp;
|
||
var lightSide = this._lightSide;
|
||
var lightForward = this._lightForward;
|
||
Matrix4x4.createFromQuaternion(light._transform.rotation, lightWorld);
|
||
lightSide.setValue(lightWorldE[0], lightWorldE[1], lightWorldE[2]);
|
||
lightUp.setValue(lightWorldE[4], lightWorldE[5], lightWorldE[6]);
|
||
lightForward.setValue(-lightWorldE[8], -lightWorldE[9], -lightWorldE[10]);
|
||
var atlasResolution = light._shadowResolution;
|
||
var cascadesMode = light._shadowCascadesMode;
|
||
var cascadesCount;
|
||
var shadowTileResolution;
|
||
var shadowMapWidth, shadowMapHeight;
|
||
if (cascadesMode == exports.ShadowCascadesMode.NoCascades) {
|
||
cascadesCount = 1;
|
||
shadowTileResolution = atlasResolution;
|
||
shadowMapWidth = atlasResolution;
|
||
shadowMapHeight = atlasResolution;
|
||
}
|
||
else {
|
||
cascadesCount = cascadesMode == exports.ShadowCascadesMode.TwoCascades ? 2 : 4;
|
||
shadowTileResolution = ShadowUtils.getMaxTileResolutionInAtlas(atlasResolution, atlasResolution, cascadesCount);
|
||
shadowMapWidth = shadowTileResolution * 2;
|
||
shadowMapHeight = cascadesMode == exports.ShadowCascadesMode.TwoCascades ? shadowTileResolution : shadowTileResolution * 2;
|
||
}
|
||
this._cascadeCount = cascadesCount;
|
||
this._shadowMapWidth = shadowMapWidth;
|
||
this._shadowMapHeight = shadowMapHeight;
|
||
var splitDistance = ShadowCasterPass._cascadesSplitDistance;
|
||
var frustumPlanes = ShadowCasterPass._frustumPlanes;
|
||
var cameraNear = camera.nearPlane;
|
||
var shadowFar = Math.min(camera.farPlane, light._shadowDistance);
|
||
var shadowMatrices = this._shadowMatrices;
|
||
var boundSpheres = this._splitBoundSpheres;
|
||
ShadowUtils.getCascadesSplitDistance(light._shadowTwoCascadeSplits, light._shadowFourCascadeSplits, cameraNear, shadowFar, camera.fieldOfView * MathUtils3D.Deg2Rad, camera.aspectRatio, cascadesMode, splitDistance);
|
||
ShadowUtils.getCameraFrustumPlanes(camera.projectionViewMatrix, frustumPlanes);
|
||
var forward = ShadowCasterPass._tempVector30;
|
||
camera._transform.getForward(forward);
|
||
Vector3.normalize(forward, forward);
|
||
for (var i = 0; i < cascadesCount; i++) {
|
||
var sliceData = this._shadowSliceDatas[i];
|
||
sliceData.sphereCenterZ = ShadowUtils.getBoundSphereByFrustum(splitDistance[i], splitDistance[i + 1], camera.fieldOfView * MathUtils3D.Deg2Rad, camera.aspectRatio, camera._transform.position, forward, sliceData.splitBoundSphere);
|
||
ShadowUtils.getDirectionLightShadowCullPlanes(frustumPlanes, i, splitDistance, cameraNear, lightForward, sliceData);
|
||
ShadowUtils.getDirectionalLightMatrices(lightUp, lightSide, lightForward, i, light._shadowNearPlane, shadowTileResolution, sliceData, shadowMatrices);
|
||
if (cascadesCount > 1)
|
||
ShadowUtils.applySliceTransform(sliceData, shadowMapWidth, shadowMapHeight, i, shadowMatrices);
|
||
}
|
||
ShadowUtils.prepareShadowReceiverShaderValues(light, shadowMapWidth, shadowMapHeight, this._shadowSliceDatas, cascadesCount, this._shadowMapSize, this._shadowParams, shadowMatrices, boundSpheres);
|
||
break;
|
||
case exports.ShadowLightType.SpotLight:
|
||
this._light = light;
|
||
var lightWorld = ShadowCasterPass._tempMatrix0;
|
||
var lightForward = this._lightForward;
|
||
var shadowResolution = this._light._shadowResolution;
|
||
this._shadowMapWidth = shadowResolution;
|
||
this._shadowMapHeight = shadowResolution;
|
||
var shadowSpotData = this._shadowSpotData;
|
||
ShadowUtils.getSpotLightShadowData(shadowSpotData, this._light, shadowResolution, this._shadowParams, this._shadowSpotMatrices, this._shadowSpotMapSize);
|
||
break;
|
||
case exports.ShadowLightType.PointLight:
|
||
break;
|
||
default:
|
||
throw ("There is no shadow of this type");
|
||
}
|
||
}
|
||
render(context, scene, lightType) {
|
||
switch (lightType) {
|
||
case exports.ShadowLightType.DirectionLight:
|
||
var shaderValues = scene._shaderValues;
|
||
context.pipelineMode = "ShadowCaster";
|
||
ShaderData.setRuntimeValueMode(false);
|
||
var shadowMap = this._shadowDirectLightMap = ShadowUtils.getTemporaryShadowTexture(this._shadowMapWidth, this._shadowMapHeight, Laya.RenderTextureDepthFormat.DEPTH_16);
|
||
shadowMap._start();
|
||
var light = this._light;
|
||
for (var i = 0, n = this._cascadeCount; i < n; i++) {
|
||
var sliceData = this._shadowSliceDatas[i];
|
||
ShadowUtils.getShadowBias(light, sliceData.projectionMatrix, sliceData.resolution, this._shadowBias);
|
||
this._setupShadowCasterShaderValues(context, shaderValues, sliceData, this._lightForward, this._shadowParams, this._shadowBias, exports.LightType.Directional);
|
||
var shadowCullInfo = FrustumCulling._shadowCullInfo;
|
||
shadowCullInfo.position = sliceData.position;
|
||
shadowCullInfo.cullPlanes = sliceData.cullPlanes;
|
||
shadowCullInfo.cullPlaneCount = sliceData.cullPlaneCount;
|
||
shadowCullInfo.cullSphere = sliceData.splitBoundSphere;
|
||
shadowCullInfo.direction = this._lightForward;
|
||
var needRender = FrustumCulling.cullingShadow(shadowCullInfo, scene, context);
|
||
context.cameraShaderValue = sliceData.cameraShaderValue;
|
||
Camera._updateMark++;
|
||
var gl = Laya.LayaGL.instance;
|
||
var resolution = sliceData.resolution;
|
||
var offsetX = sliceData.offsetX;
|
||
var offsetY = sliceData.offsetY;
|
||
gl.enable(gl.SCISSOR_TEST);
|
||
gl.viewport(offsetX, offsetY, resolution, resolution);
|
||
gl.scissor(offsetX, offsetY, resolution, resolution);
|
||
gl.clear(gl.DEPTH_BUFFER_BIT);
|
||
if (needRender) {
|
||
gl.scissor(offsetX + 1, offsetY + 1, resolution - 2, resolution - 2);
|
||
scene._opaqueQueue._render(context);
|
||
}
|
||
}
|
||
shadowMap._end();
|
||
this._setupShadowReceiverShaderValues(shaderValues);
|
||
ShaderData.setRuntimeValueMode(true);
|
||
context.pipelineMode = context.configPipeLineMode;
|
||
break;
|
||
case exports.ShadowLightType.SpotLight:
|
||
var shaderValues = scene._shaderValues;
|
||
context.pipelineMode = "ShadowCaster";
|
||
ShaderData.setRuntimeValueMode(false);
|
||
var spotlight = this._light;
|
||
var shadowMap = this._shadowSpotLightMap = ShadowUtils.getTemporaryShadowTexture(this._shadowMapWidth, this._shadowMapHeight, Laya.RenderTextureDepthFormat.DEPTH_16);
|
||
shadowMap._start();
|
||
var shadowSpotData = this._shadowSpotData;
|
||
ShadowUtils.getShadowBias(spotlight, shadowSpotData.projectionMatrix, shadowSpotData.resolution, this._shadowBias);
|
||
this._setupShadowCasterShaderValues(context, shaderValues, shadowSpotData, this._light.transform.position, this._shadowParams, this._shadowBias, exports.LightType.Spot);
|
||
var needRender = FrustumCulling.cullingSpotShadow(shadowSpotData.cameraCullInfo, scene, context);
|
||
context.cameraShaderValue = shadowSpotData.cameraShaderValue;
|
||
Camera._updateMark++;
|
||
var gl = Laya.LayaGL.instance;
|
||
gl.enable(gl.SCISSOR_TEST);
|
||
gl.viewport(shadowSpotData.offsetX, shadowSpotData.offsetY, shadowSpotData.resolution, shadowSpotData.resolution);
|
||
gl.scissor(shadowSpotData.offsetX, shadowSpotData.offsetY, shadowSpotData.resolution, shadowSpotData.resolution);
|
||
gl.clear(gl.DEPTH_BUFFER_BIT);
|
||
if (needRender) {
|
||
gl.scissor(shadowSpotData.offsetX, shadowSpotData.offsetY, shadowSpotData.resolution, shadowSpotData.resolution);
|
||
scene._opaqueQueue._render(context);
|
||
}
|
||
shadowMap._end();
|
||
this._setupSpotShadowReceiverShaderValues(shaderValues);
|
||
ShaderData.setRuntimeValueMode(true);
|
||
context.pipelineMode = context.configPipeLineMode;
|
||
break;
|
||
case exports.ShadowLightType.PointLight:
|
||
break;
|
||
default:
|
||
throw ("There is no shadow of this type");
|
||
}
|
||
}
|
||
cleanUp() {
|
||
this._shadowDirectLightMap && RenderTexture.recoverToPool(this._shadowDirectLightMap);
|
||
this._shadowSpotLightMap && RenderTexture.recoverToPool(this._shadowSpotLightMap);
|
||
this._shadowDirectLightMap = null;
|
||
this._shadowSpotLightMap = null;
|
||
this._light = null;
|
||
}
|
||
}
|
||
ShadowCasterPass._tempVector30 = new Vector3();
|
||
ShadowCasterPass._tempMatrix0 = new Matrix4x4();
|
||
ShadowCasterPass.SHADOW_BIAS = Shader3D.propertyNameToID("u_ShadowBias");
|
||
ShadowCasterPass.SHADOW_LIGHT_DIRECTION = Shader3D.propertyNameToID("u_ShadowLightDirection");
|
||
ShadowCasterPass.SHADOW_SPLIT_SPHERES = Shader3D.propertyNameToID("u_ShadowSplitSpheres");
|
||
ShadowCasterPass.SHADOW_MATRICES = Shader3D.propertyNameToID("u_ShadowMatrices");
|
||
ShadowCasterPass.SHADOW_MAP_SIZE = Shader3D.propertyNameToID("u_ShadowMapSize");
|
||
ShadowCasterPass.SHADOW_MAP = Shader3D.propertyNameToID("u_ShadowMap");
|
||
ShadowCasterPass.SHADOW_PARAMS = Shader3D.propertyNameToID("u_ShadowParams");
|
||
ShadowCasterPass.SHADOW_SPOTMAP_SIZE = Shader3D.propertyNameToID("u_SpotShadowMapSize");
|
||
ShadowCasterPass.SHADOW_SPOTMAP = Shader3D.propertyNameToID("u_SpotShadowMap");
|
||
ShadowCasterPass.SHADOW_SPOTMATRICES = Shader3D.propertyNameToID("u_SpotViewProjectMatrix");
|
||
ShadowCasterPass._maxCascades = 4;
|
||
ShadowCasterPass._cascadesSplitDistance = new Array(ShadowCasterPass._maxCascades + 1);
|
||
ShadowCasterPass._frustumPlanes = new Array(new Plane(new Vector3()), new Plane(new Vector3()), new Plane(new Vector3()), new Plane(new Vector3()), new Plane(new Vector3()), new Plane(new Vector3()));
|
||
|
||
class DynamicBatchManager {
|
||
constructor() {
|
||
this._batchRenderElementPool = [];
|
||
}
|
||
static _registerManager(manager) {
|
||
DynamicBatchManager._managers.push(manager);
|
||
}
|
||
_clear() {
|
||
this._batchRenderElementPoolIndex = 0;
|
||
}
|
||
_getBatchRenderElementFromPool() {
|
||
throw "StaticBatch:must override this function.";
|
||
}
|
||
dispose() {
|
||
}
|
||
}
|
||
DynamicBatchManager._managers = [];
|
||
|
||
class ReflectionProbeList extends SingletonList {
|
||
constructor() {
|
||
super();
|
||
}
|
||
add(singleElement) {
|
||
this._add(singleElement);
|
||
singleElement._setIndexInReflectionList(this.length++);
|
||
}
|
||
remove(singleElement) {
|
||
var index = singleElement._getIndexInReflectionList();
|
||
this.length--;
|
||
if (index !== this.length) {
|
||
var end = this.elements[this.length];
|
||
this.elements[index] = end;
|
||
end._setIndexInReflectionList(index);
|
||
}
|
||
singleElement._setIndexInReflectionList(-1);
|
||
}
|
||
}
|
||
|
||
class ReflectionProbeManager {
|
||
constructor() {
|
||
this._reflectionProbes = new ReflectionProbeList();
|
||
this._motionObjects = new SingletonList();
|
||
this._needUpdateAllRender = false;
|
||
this._sceneReflectionProbe = new ReflectionProbe();
|
||
this._sceneReflectionProbe.bounds = new Bounds(new Vector3(0, 0, 0), new Vector3(0, 0, 0));
|
||
this._sceneReflectionProbe.boxProjection = false;
|
||
this._sceneReflectionProbe._isScene = true;
|
||
}
|
||
set sceneReflectionProbe(value) {
|
||
this._sceneReflectionProbe.reflectionTexture = value;
|
||
}
|
||
set sceneReflectionCubeHDRParam(value) {
|
||
this._sceneReflectionProbe.reflectionHDRParams = value;
|
||
}
|
||
_updateMotionObjects(baseRender) {
|
||
if (this._reflectionProbes.length == 0) {
|
||
baseRender._probReflection = this._sceneReflectionProbe;
|
||
return;
|
||
}
|
||
var elements = this._reflectionProbes.elements;
|
||
var maxOverlap = 0;
|
||
var mainProbe;
|
||
var renderBounds = baseRender.bounds;
|
||
var overlop;
|
||
for (var i = 0, n = this._reflectionProbes.length; i < n; i++) {
|
||
var renflectProbe = elements[i];
|
||
if (!mainProbe) {
|
||
overlop = renderBounds.calculateBoundsintersection(renflectProbe.bounds);
|
||
if (overlop < maxOverlap)
|
||
continue;
|
||
}
|
||
else {
|
||
if (mainProbe.importance > renflectProbe.importance)
|
||
continue;
|
||
overlop = renderBounds.calculateBoundsintersection(renflectProbe.bounds);
|
||
if (overlop < maxOverlap && mainProbe.importance == renflectProbe.importance)
|
||
continue;
|
||
}
|
||
mainProbe = renflectProbe;
|
||
maxOverlap = overlop;
|
||
}
|
||
if (!mainProbe && this._sceneReflectionProbe)
|
||
mainProbe = this._sceneReflectionProbe;
|
||
baseRender._probReflection = mainProbe;
|
||
}
|
||
add(reflectionProbe) {
|
||
this._reflectionProbes.add(reflectionProbe);
|
||
this._needUpdateAllRender = true;
|
||
}
|
||
remove(reflectionProbe) {
|
||
this._reflectionProbes.remove(reflectionProbe);
|
||
this._needUpdateAllRender = true;
|
||
}
|
||
addMotionObject(renderObject) {
|
||
this._motionObjects.add(renderObject);
|
||
}
|
||
update() {
|
||
var elements = this._motionObjects.elements;
|
||
for (var i = 0, n = this._motionObjects.length; i < n; i++) {
|
||
this._updateMotionObjects(elements[i]);
|
||
}
|
||
this.clearMotionObjects();
|
||
}
|
||
updateAllRenderObjects(baseRenders) {
|
||
var elements = baseRenders.elements;
|
||
for (var i = 0, n = baseRenders.length; i < n; i++) {
|
||
this._updateMotionObjects(elements[i]);
|
||
}
|
||
this._needUpdateAllRender = false;
|
||
}
|
||
clearMotionObjects() {
|
||
this._motionObjects.length = 0;
|
||
}
|
||
destroy() {
|
||
}
|
||
}
|
||
|
||
(function (AmbientMode) {
|
||
AmbientMode[AmbientMode["SolidColor"] = 0] = "SolidColor";
|
||
AmbientMode[AmbientMode["SphericalHarmonics"] = 1] = "SphericalHarmonics";
|
||
})(exports.AmbientMode || (exports.AmbientMode = {}));
|
||
class Scene3D extends Laya.Sprite {
|
||
constructor() {
|
||
super();
|
||
this._lightCount = 0;
|
||
this._pointLights = new LightQueue();
|
||
this._spotLights = new LightQueue();
|
||
this._directionLights = new LightQueue();
|
||
this._alternateLights = new AlternateLightQueue();
|
||
this._lightmaps = [];
|
||
this._skyRenderer = new SkyRenderer();
|
||
this._input = new Input3D();
|
||
this._timer = Laya.ILaya.timer;
|
||
this._time = 0;
|
||
this._shCoefficients = new Array(7);
|
||
this._ambientMode = exports.AmbientMode.SolidColor;
|
||
this._ambientSphericalHarmonics = new SphericalHarmonicsL2();
|
||
this._ambientSphericalHarmonicsIntensity = 1.0;
|
||
this._reflectionDecodeFormat = Laya.TextureDecodeFormat.Normal;
|
||
this._reflectionIntensity = 1.0;
|
||
this._collsionTestList = [];
|
||
this._renders = new SimpleSingletonList();
|
||
this._opaqueQueue = new RenderQueue(false);
|
||
this._transparentQueue = new RenderQueue(true);
|
||
this._cameraPool = [];
|
||
this._animatorPool = new SimpleSingletonList();
|
||
this._scriptPool = new Array();
|
||
this._tempScriptPool = new Array();
|
||
this._needClearScriptPool = false;
|
||
this._reflectionCubeHDRParams = new Vector4();
|
||
this._reflectionProbeManager = new ReflectionProbeManager();
|
||
this.currentCreationLayer = Math.pow(2, 0);
|
||
this.enableLight = true;
|
||
this._key = new Laya.SubmitKey();
|
||
this._pickIdToSprite = new Object();
|
||
this._reflectionMode = 0;
|
||
if (!Config3D._config.isUseCannonPhysicsEngine && Physics3D._bullet)
|
||
this._physicsSimulation = new Laya.PhysicsSimulation(Scene3D.physicsSettings);
|
||
else if (Physics3D._cannon) {
|
||
this._cannonPhysicsSimulation = new Laya.CannonPhysicsSimulation(Scene3D.cannonPhysicsSettings);
|
||
}
|
||
this._shaderValues = new ShaderData(null);
|
||
this.enableFog = false;
|
||
this.fogStart = 300;
|
||
this.fogRange = 1000;
|
||
this.fogColor = new Vector3(0.7, 0.7, 0.7);
|
||
this.ambientColor = new Vector3(0.212, 0.227, 0.259);
|
||
this.reflectionIntensity = 1.0;
|
||
this.reflection = TextureCube.blackTexture;
|
||
for (var i = 0; i < 7; i++)
|
||
this._shCoefficients[i] = new Vector4();
|
||
this._reflectionProbeManager.sceneReflectionCubeHDRParam = this._reflectionCubeHDRParams;
|
||
this._scene = this;
|
||
this._input.__init__(Laya.Render.canvas, this);
|
||
if (Scene3D.octreeCulling)
|
||
this._octree = new BoundsOctree(Scene3D.octreeInitialSize, Scene3D.octreeInitialCenter, Scene3D.octreeMinNodeSize, Scene3D.octreeLooseness);
|
||
if (FrustumCulling.debugFrustumCulling) {
|
||
this._debugTool = new PixelLineSprite3D();
|
||
var lineMaterial = new PixelLineMaterial();
|
||
lineMaterial.renderQueue = Material.RENDERQUEUE_TRANSPARENT;
|
||
lineMaterial.alphaTest = false;
|
||
lineMaterial.depthWrite = false;
|
||
lineMaterial.cull = RenderState.CULL_BACK;
|
||
lineMaterial.blend = RenderState.BLEND_ENABLE_ALL;
|
||
lineMaterial.blendSrc = RenderState.BLENDPARAM_SRC_ALPHA;
|
||
lineMaterial.blendDst = RenderState.BLENDPARAM_ONE_MINUS_SRC_ALPHA;
|
||
lineMaterial.depthTest = RenderState.DEPTHTEST_LESS;
|
||
this._debugTool.pixelLineRenderer.sharedMaterial = lineMaterial;
|
||
}
|
||
}
|
||
static __init__() {
|
||
var con = Config3D._config;
|
||
var multiLighting = con._multiLighting;
|
||
if (multiLighting) {
|
||
const width = 4;
|
||
var maxLightCount = con.maxLightCount;
|
||
var clusterSlices = con.lightClusterCount;
|
||
Cluster.instance = new Cluster(clusterSlices.x, clusterSlices.y, clusterSlices.z, Math.min(con.maxLightCount, con._maxAreaLightCountPerClusterAverage));
|
||
Scene3D._lightTexture = Utils3D._createFloatTextureBuffer(width, maxLightCount);
|
||
Scene3D._lightTexture.lock = true;
|
||
Scene3D._lightPixles = new Float32Array(maxLightCount * width * 4);
|
||
}
|
||
Scene3DShaderDeclaration.SHADERDEFINE_FOG = Shader3D.getDefineByName("FOG");
|
||
Scene3DShaderDeclaration.SHADERDEFINE_DIRECTIONLIGHT = Shader3D.getDefineByName("DIRECTIONLIGHT");
|
||
Scene3DShaderDeclaration.SHADERDEFINE_POINTLIGHT = Shader3D.getDefineByName("POINTLIGHT");
|
||
Scene3DShaderDeclaration.SHADERDEFINE_SPOTLIGHT = Shader3D.getDefineByName("SPOTLIGHT");
|
||
Scene3DShaderDeclaration.SHADERDEFINE_SHADOW = Shader3D.getDefineByName("SHADOW");
|
||
Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_CASCADE = Shader3D.getDefineByName("SHADOW_CASCADE");
|
||
Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_SOFT_SHADOW_LOW = Shader3D.getDefineByName("SHADOW_SOFT_SHADOW_LOW");
|
||
Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_SOFT_SHADOW_HIGH = Shader3D.getDefineByName("SHADOW_SOFT_SHADOW_HIGH");
|
||
Scene3DShaderDeclaration.SHADERDEFINE_GI_AMBIENT_SH = Shader3D.getDefineByName("GI_AMBIENT_SH");
|
||
Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_SPOT = Shader3D.getDefineByName("SHADOW_SPOT");
|
||
Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_SPOT_SOFT_SHADOW_LOW = Shader3D.getDefineByName("SHADOW_SPOT_SOFT_SHADOW_LOW");
|
||
Scene3DShaderDeclaration.SHADERDEFINE_SHADOW_SPOT_SOFT_SHADOW_HIGH = Shader3D.getDefineByName("SHADOW_SPOT_SOFT_SHADOW_HIGH");
|
||
var config = Config3D._config;
|
||
var configShaderValue = Scene3D._configDefineValues;
|
||
(config._multiLighting) || (configShaderValue.add(Shader3D.SHADERDEFINE_LEGACYSINGALLIGHTING));
|
||
if (Laya.LayaGL.layaGPUInstance._isWebGL2)
|
||
configShaderValue.add(Shader3D.SHADERDEFINE_GRAPHICS_API_GLES3);
|
||
else
|
||
configShaderValue.add(Shader3D.SHADERDEFINE_GRAPHICS_API_GLES2);
|
||
switch (config.pbrRenderQuality) {
|
||
case exports.PBRRenderQuality.High:
|
||
configShaderValue.add(PBRMaterial.SHADERDEFINE_LAYA_PBR_BRDF_HIGH);
|
||
break;
|
||
case exports.PBRRenderQuality.Low:
|
||
configShaderValue.add(PBRMaterial.SHADERDEFINE_LAYA_PBR_BRDF_LOW);
|
||
break;
|
||
default:
|
||
throw "Scene3D:unknown shader quality.";
|
||
}
|
||
if (config.isUseCannonPhysicsEngine) {
|
||
Physics3D._cannon && (Scene3D.cannonPhysicsSettings = new Laya.CannonPhysicsSettings());
|
||
}
|
||
else {
|
||
Physics3D._bullet && (Scene3D.physicsSettings = new Laya.PhysicsSettings());
|
||
}
|
||
}
|
||
static load(url, complete) {
|
||
Laya.ILaya.loader.create(url, complete, null, Scene3D.HIERARCHY);
|
||
}
|
||
get url() {
|
||
return this._url;
|
||
}
|
||
get enableFog() {
|
||
return this._enableFog;
|
||
}
|
||
set enableFog(value) {
|
||
if (this._enableFog !== value) {
|
||
this._enableFog = value;
|
||
if (value) {
|
||
this._shaderValues.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_FOG);
|
||
}
|
||
else
|
||
this._shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_FOG);
|
||
}
|
||
}
|
||
get fogColor() {
|
||
return this._shaderValues.getVector3(Scene3D.FOGCOLOR);
|
||
}
|
||
set fogColor(value) {
|
||
this._shaderValues.setVector3(Scene3D.FOGCOLOR, value);
|
||
}
|
||
get fogStart() {
|
||
return this._shaderValues.getNumber(Scene3D.FOGSTART);
|
||
}
|
||
set fogStart(value) {
|
||
this._shaderValues.setNumber(Scene3D.FOGSTART, value);
|
||
}
|
||
get fogRange() {
|
||
return this._shaderValues.getNumber(Scene3D.FOGRANGE);
|
||
}
|
||
set fogRange(value) {
|
||
this._shaderValues.setNumber(Scene3D.FOGRANGE, value);
|
||
}
|
||
get ambientMode() {
|
||
return this._ambientMode;
|
||
}
|
||
set ambientMode(value) {
|
||
if (this._ambientMode !== value) {
|
||
switch (value) {
|
||
case exports.AmbientMode.SolidColor:
|
||
this._shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_GI_AMBIENT_SH);
|
||
break;
|
||
case exports.AmbientMode.SphericalHarmonics:
|
||
this._shaderValues.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_GI_AMBIENT_SH);
|
||
break;
|
||
default:
|
||
throw "Scene3D: unknown ambientMode.";
|
||
}
|
||
this._ambientMode = value;
|
||
}
|
||
}
|
||
get ambientColor() {
|
||
return this._shaderValues.getVector3(Scene3D.AMBIENTCOLOR);
|
||
}
|
||
set ambientColor(value) {
|
||
this._shaderValues.setVector3(Scene3D.AMBIENTCOLOR, value);
|
||
}
|
||
get ambientSphericalHarmonics() {
|
||
return this._ambientSphericalHarmonics;
|
||
}
|
||
set ambientSphericalHarmonics(value) {
|
||
var originalSH = value || SphericalHarmonicsL2._default;
|
||
this._applySHCoefficients(originalSH, Math.pow(this._ambientSphericalHarmonicsIntensity, 2.2));
|
||
if (this._ambientSphericalHarmonics != value)
|
||
value.cloneTo(this._ambientSphericalHarmonics);
|
||
}
|
||
get ambientSphericalHarmonicsIntensity() {
|
||
return this._ambientSphericalHarmonicsIntensity;
|
||
}
|
||
set ambientSphericalHarmonicsIntensity(value) {
|
||
value = Math.max(Math.min(value, 8.0), 0.0);
|
||
if (this._ambientSphericalHarmonicsIntensity !== value) {
|
||
var originalSH = this._ambientSphericalHarmonics || SphericalHarmonicsL2._default;
|
||
this._applySHCoefficients(originalSH, Math.pow(value, 2.2));
|
||
this._ambientSphericalHarmonicsIntensity = value;
|
||
}
|
||
}
|
||
get reflection() {
|
||
return this._reflection;
|
||
}
|
||
set reflection(value) {
|
||
value = value ? value : TextureCube.blackTexture;
|
||
if (this._reflection != value) {
|
||
value._addReference();
|
||
this._reflectionProbeManager.sceneReflectionProbe = value;
|
||
this._reflection = value;
|
||
this._reflectionProbeManager._needUpdateAllRender = true;
|
||
}
|
||
}
|
||
get reflectionDecodingFormat() {
|
||
return this._reflectionDecodeFormat;
|
||
}
|
||
set reflectionDecodingFormat(value) {
|
||
if (this._reflectionDecodeFormat != value) {
|
||
this._reflectionCubeHDRParams.x = this._reflectionIntensity;
|
||
if (this._reflectionDecodeFormat == Laya.TextureDecodeFormat.RGBM)
|
||
this._reflectionCubeHDRParams.x *= 5.0;
|
||
this._reflectionDecodeFormat = value;
|
||
this._reflectionProbeManager.sceneReflectionCubeHDRParam = this._reflectionCubeHDRParams;
|
||
}
|
||
}
|
||
get reflectionIntensity() {
|
||
return this._reflectionIntensity;
|
||
}
|
||
set reflectionIntensity(value) {
|
||
value = Math.max(Math.min(value, 1.0), 0.0);
|
||
this._reflectionCubeHDRParams.x = value;
|
||
if (this._reflectionDecodeFormat == Laya.TextureDecodeFormat.RGBM)
|
||
this._reflectionCubeHDRParams.x *= 5.0;
|
||
this._reflectionIntensity = value;
|
||
this._reflectionProbeManager.sceneReflectionCubeHDRParam = this._reflectionCubeHDRParams;
|
||
}
|
||
get skyRenderer() {
|
||
return this._skyRenderer;
|
||
}
|
||
get physicsSimulation() {
|
||
return this._physicsSimulation;
|
||
}
|
||
get cannonPhysicsSimulation() {
|
||
return this._cannonPhysicsSimulation;
|
||
}
|
||
get timer() {
|
||
return this._timer;
|
||
}
|
||
set timer(value) {
|
||
this._timer = value;
|
||
}
|
||
get input() {
|
||
return this._input;
|
||
}
|
||
get lightmaps() {
|
||
return this._lightmaps.slice();
|
||
}
|
||
set lightmaps(value) {
|
||
var maps = this._lightmaps;
|
||
if (maps) {
|
||
for (var i = 0, n = maps.length; i < n; i++) {
|
||
var map = maps[i];
|
||
map.lightmapColor._removeReference();
|
||
map.lightmapDirection._removeReference();
|
||
}
|
||
}
|
||
if (value) {
|
||
var count = value.length;
|
||
maps.length = count;
|
||
for (i = 0; i < count; i++) {
|
||
var map = value[i];
|
||
map.lightmapColor && map.lightmapColor._addReference();
|
||
map.lightmapDirection && map.lightmapDirection._addReference();
|
||
maps[i] = map;
|
||
}
|
||
}
|
||
else {
|
||
maps.length = 0;
|
||
}
|
||
}
|
||
_applySHCoefficients(originalSH, intensity) {
|
||
var optSH = this._shCoefficients;
|
||
for (var i = 0; i < 3; i++) {
|
||
var shaderSHA = optSH[i];
|
||
var shaderSHB = optSH[i + 3];
|
||
shaderSHA.setValue(originalSH.getCoefficient(i, 3) * intensity, originalSH.getCoefficient(i, 1) * intensity, originalSH.getCoefficient(i, 2) * intensity, (originalSH.getCoefficient(i, 0) - originalSH.getCoefficient(i, 6)) * intensity);
|
||
shaderSHB.setValue(originalSH.getCoefficient(i, 4) * intensity, originalSH.getCoefficient(i, 5) * intensity, originalSH.getCoefficient(i, 6) * 3 * intensity, originalSH.getCoefficient(i, 7) * intensity);
|
||
}
|
||
optSH[6].setValue(originalSH.getCoefficient(0, 8) * intensity, originalSH.getCoefficient(1, 8) * intensity, originalSH.getCoefficient(2, 8) * intensity, 1);
|
||
var shaderValues = this._shaderValues;
|
||
shaderValues.setVector(Scene3D.AMBIENTSHAR, optSH[0]);
|
||
shaderValues.setVector(Scene3D.AMBIENTSHAG, optSH[1]);
|
||
shaderValues.setVector(Scene3D.AMBIENTSHAB, optSH[2]);
|
||
shaderValues.setVector(Scene3D.AMBIENTSHBR, optSH[3]);
|
||
shaderValues.setVector(Scene3D.AMBIENTSHBG, optSH[4]);
|
||
shaderValues.setVector(Scene3D.AMBIENTSHBB, optSH[5]);
|
||
shaderValues.setVector(Scene3D.AMBIENTSHC, optSH[6]);
|
||
}
|
||
_update() {
|
||
Laya.PerformancePlugin.begainSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D);
|
||
var delta = this.timer._delta / 1000;
|
||
this._time += delta;
|
||
this._shaderValues.setNumber(Scene3D.TIME, this._time);
|
||
Laya.PerformancePlugin.begainSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D_PHYSICS);
|
||
var simulation = this._physicsSimulation;
|
||
if (Physics3D._enablePhysics && !Laya.PhysicsSimulation.disableSimulation && !Config3D._config.isUseCannonPhysicsEngine) {
|
||
simulation._updatePhysicsTransformFromRender();
|
||
Laya.PhysicsComponent._addUpdateList = false;
|
||
Laya.PerformancePlugin.begainSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D_PHYSICS_SIMULATE);
|
||
simulation._simulate(delta);
|
||
Laya.PerformancePlugin.endSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D_PHYSICS_SIMULATE);
|
||
Laya.PerformancePlugin.begainSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D_PHYSICS_CHARACTORCOLLISION);
|
||
simulation._updateCharacters();
|
||
Laya.PhysicsComponent._addUpdateList = true;
|
||
simulation._updateCollisions();
|
||
Laya.PerformancePlugin.endSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D_PHYSICS_CHARACTORCOLLISION);
|
||
Laya.PerformancePlugin.begainSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D_PHYSICS_EVENTSCRIPTS);
|
||
simulation._eventScripts();
|
||
Laya.PerformancePlugin.endSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D_PHYSICS_EVENTSCRIPTS);
|
||
}
|
||
if (Physics3D._cannon && Config3D._config.isUseCannonPhysicsEngine) {
|
||
var cannonSimulation = this._cannonPhysicsSimulation;
|
||
cannonSimulation._updatePhysicsTransformFromRender();
|
||
Laya.CannonPhysicsComponent._addUpdateList = false;
|
||
cannonSimulation._simulate(delta);
|
||
Laya.CannonPhysicsComponent._addUpdateList = true;
|
||
cannonSimulation._updateCollisions();
|
||
cannonSimulation._eventScripts();
|
||
}
|
||
Laya.PerformancePlugin.endSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D_PHYSICS);
|
||
Laya.PerformancePlugin.begainSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D_UPDATESCRIPT);
|
||
this._input._update();
|
||
this._clearScript();
|
||
this._updateScript();
|
||
Animator._update(this);
|
||
Laya.VideoTexture._update();
|
||
if (this._reflectionProbeManager._needUpdateAllRender)
|
||
this._reflectionProbeManager.updateAllRenderObjects(this._renders);
|
||
else
|
||
this._reflectionProbeManager.update();
|
||
this._lateUpdateScript();
|
||
Laya.PerformancePlugin.endSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D_UPDATESCRIPT);
|
||
Laya.PerformancePlugin.endSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D);
|
||
}
|
||
_binarySearchIndexInCameraPool(camera) {
|
||
var start = 0;
|
||
var end = this._cameraPool.length - 1;
|
||
var mid;
|
||
while (start <= end) {
|
||
mid = Math.floor((start + end) / 2);
|
||
var midValue = this._cameraPool[mid]._renderingOrder;
|
||
if (midValue == camera._renderingOrder)
|
||
return mid;
|
||
else if (midValue > camera._renderingOrder)
|
||
end = mid - 1;
|
||
else
|
||
start = mid + 1;
|
||
}
|
||
return start;
|
||
}
|
||
_allotPickColorByID(id, pickColor) {
|
||
var pickColorR = Math.floor(id / (255 * 255));
|
||
id -= pickColorR * 255 * 255;
|
||
var pickColorG = Math.floor(id / 255);
|
||
id -= pickColorG * 255;
|
||
var pickColorB = id;
|
||
pickColor.x = pickColorR / 255;
|
||
pickColor.y = pickColorG / 255;
|
||
pickColor.z = pickColorB / 255;
|
||
pickColor.w = 1.0;
|
||
}
|
||
_searchIDByPickColor(pickColor) {
|
||
var id = pickColor.x * 255 * 255 + pickColor.y * 255 + pickColor.z;
|
||
return id;
|
||
}
|
||
onEnable() {
|
||
this._input._onCanvasEvent(Laya.Render.canvas);
|
||
}
|
||
onDisable() {
|
||
this._input._offCanvasEvent(Laya.Render.canvas);
|
||
}
|
||
_setCreateURL(url) {
|
||
this._url = Laya.URL.formatURL(url);
|
||
}
|
||
_getGroup() {
|
||
return this._group;
|
||
}
|
||
_setGroup(value) {
|
||
this._group = value;
|
||
}
|
||
_clearScript() {
|
||
if (this._needClearScriptPool) {
|
||
var scripts = this._scriptPool;
|
||
for (var i = 0, n = scripts.length; i < n; i++) {
|
||
var script = scripts[i];
|
||
if (script) {
|
||
script._indexInPool = this._tempScriptPool.length;
|
||
this._tempScriptPool.push(script);
|
||
}
|
||
}
|
||
this._scriptPool = this._tempScriptPool;
|
||
scripts.length = 0;
|
||
this._tempScriptPool = scripts;
|
||
this._needClearScriptPool = false;
|
||
}
|
||
}
|
||
_updateScript() {
|
||
var scripts = this._scriptPool;
|
||
for (var i = 0, n = scripts.length; i < n; i++) {
|
||
var script = scripts[i];
|
||
(script && script.enabled) && (script.onUpdate());
|
||
}
|
||
}
|
||
_lateUpdateScript() {
|
||
var scripts = this._scriptPool;
|
||
for (var i = 0, n = scripts.length; i < n; i++) {
|
||
var script = scripts[i];
|
||
(script && script.enabled) && (script.onLateUpdate());
|
||
}
|
||
}
|
||
_onActive() {
|
||
super._onActive();
|
||
Laya.ILaya.stage._scene3Ds.push(this);
|
||
}
|
||
_onInActive() {
|
||
super._onInActive();
|
||
var scenes = Laya.ILaya.stage._scene3Ds;
|
||
scenes.splice(scenes.indexOf(this), 1);
|
||
}
|
||
_prepareSceneToRender() {
|
||
var shaderValues = this._shaderValues;
|
||
var multiLighting = Config3D._config._multiLighting;
|
||
if (multiLighting) {
|
||
var ligTex = Scene3D._lightTexture;
|
||
var ligPix = Scene3D._lightPixles;
|
||
const pixelWidth = ligTex.width;
|
||
const floatWidth = pixelWidth * 4;
|
||
var curCount = 0;
|
||
var dirCount = this._directionLights._length;
|
||
var dirElements = this._directionLights._elements;
|
||
if (dirCount > 0) {
|
||
var sunLightIndex = this._directionLights.getBrightestLight();
|
||
this._mainDirectionLight = dirElements[sunLightIndex];
|
||
this._directionLights.normalLightOrdering(sunLightIndex);
|
||
for (var i = 0; i < dirCount; i++, curCount++) {
|
||
var dirLight = dirElements[i];
|
||
var dir = dirLight._direction;
|
||
var intCor = dirLight._intensityColor;
|
||
var off = floatWidth * curCount;
|
||
Vector3.scale(dirLight.color, dirLight._intensity, intCor);
|
||
dirLight.transform.worldMatrix.getForward(dir);
|
||
Vector3.normalize(dir, dir);
|
||
ligPix[off] = intCor.x;
|
||
ligPix[off + 1] = intCor.y;
|
||
ligPix[off + 2] = intCor.z;
|
||
ligPix[off + 4] = dir.x;
|
||
ligPix[off + 5] = dir.y;
|
||
ligPix[off + 6] = dir.z;
|
||
if (i == 0) {
|
||
shaderValues.setVector3(Scene3D.SUNLIGHTDIRCOLOR, intCor);
|
||
shaderValues.setVector3(Scene3D.SUNLIGHTDIRECTION, dir);
|
||
}
|
||
}
|
||
shaderValues.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_DIRECTIONLIGHT);
|
||
}
|
||
else {
|
||
shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_DIRECTIONLIGHT);
|
||
}
|
||
var poiCount = this._pointLights._length;
|
||
if (poiCount > 0) {
|
||
var poiElements = this._pointLights._elements;
|
||
var mainPointLightIndex = this._pointLights.getBrightestLight();
|
||
this._mainPointLight = poiElements[mainPointLightIndex];
|
||
this._pointLights.normalLightOrdering(mainPointLightIndex);
|
||
for (var i = 0; i < poiCount; i++, curCount++) {
|
||
var poiLight = poiElements[i];
|
||
var pos = poiLight.transform.position;
|
||
var intCor = poiLight._intensityColor;
|
||
var off = floatWidth * curCount;
|
||
Vector3.scale(poiLight.color, poiLight._intensity, intCor);
|
||
ligPix[off] = intCor.x;
|
||
ligPix[off + 1] = intCor.y;
|
||
ligPix[off + 2] = intCor.z;
|
||
ligPix[off + 3] = poiLight.range;
|
||
ligPix[off + 4] = pos.x;
|
||
ligPix[off + 5] = pos.y;
|
||
ligPix[off + 6] = pos.z;
|
||
}
|
||
shaderValues.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_POINTLIGHT);
|
||
}
|
||
else {
|
||
shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_POINTLIGHT);
|
||
}
|
||
var spoCount = this._spotLights._length;
|
||
if (spoCount > 0) {
|
||
var spoElements = this._spotLights._elements;
|
||
var mainSpotLightIndex = this._spotLights.getBrightestLight();
|
||
this._mainSpotLight = spoElements[mainSpotLightIndex];
|
||
this._spotLights.normalLightOrdering(mainSpotLightIndex);
|
||
for (var i = 0; i < spoCount; i++, curCount++) {
|
||
var spoLight = spoElements[i];
|
||
var dir = spoLight._direction;
|
||
var pos = spoLight.transform.position;
|
||
var intCor = spoLight._intensityColor;
|
||
var off = floatWidth * curCount;
|
||
Vector3.scale(spoLight.color, spoLight._intensity, intCor);
|
||
spoLight.transform.worldMatrix.getForward(dir);
|
||
Vector3.normalize(dir, dir);
|
||
ligPix[off] = intCor.x;
|
||
ligPix[off + 1] = intCor.y;
|
||
ligPix[off + 2] = intCor.z;
|
||
ligPix[off + 3] = spoLight.range;
|
||
ligPix[off + 4] = pos.x;
|
||
ligPix[off + 5] = pos.y;
|
||
ligPix[off + 6] = pos.z;
|
||
ligPix[off + 7] = spoLight.spotAngle * Math.PI / 180;
|
||
ligPix[off + 8] = dir.x;
|
||
ligPix[off + 9] = dir.y;
|
||
ligPix[off + 10] = dir.z;
|
||
}
|
||
shaderValues.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_SPOTLIGHT);
|
||
}
|
||
else {
|
||
shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SPOTLIGHT);
|
||
}
|
||
(curCount > 0) && (ligTex.setSubPixels(0, 0, pixelWidth, curCount, ligPix, 0));
|
||
shaderValues.setTexture(Scene3D.LIGHTBUFFER, ligTex);
|
||
shaderValues.setInt(Scene3D.DIRECTIONLIGHTCOUNT, this._directionLights._length);
|
||
shaderValues.setTexture(Scene3D.CLUSTERBUFFER, Cluster.instance._clusterTexture);
|
||
}
|
||
else {
|
||
if (this._directionLights._length > 0) {
|
||
var dirLight = this._directionLights._elements[0];
|
||
this._mainDirectionLight = dirLight;
|
||
Vector3.scale(dirLight.color, dirLight._intensity, dirLight._intensityColor);
|
||
dirLight.transform.worldMatrix.getForward(dirLight._direction);
|
||
Vector3.normalize(dirLight._direction, dirLight._direction);
|
||
shaderValues.setVector3(Scene3D.LIGHTDIRCOLOR, dirLight._intensityColor);
|
||
shaderValues.setVector3(Scene3D.LIGHTDIRECTION, dirLight._direction);
|
||
shaderValues.setVector3(Scene3D.SUNLIGHTDIRCOLOR, dirLight._intensityColor);
|
||
shaderValues.setVector3(Scene3D.SUNLIGHTDIRECTION, dirLight._direction);
|
||
shaderValues.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_DIRECTIONLIGHT);
|
||
}
|
||
else {
|
||
shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_DIRECTIONLIGHT);
|
||
}
|
||
if (this._pointLights._length > 0) {
|
||
var poiLight = this._pointLights._elements[0];
|
||
this._mainPointLight = poiLight;
|
||
Vector3.scale(poiLight.color, poiLight._intensity, poiLight._intensityColor);
|
||
shaderValues.setVector3(Scene3D.POINTLIGHTCOLOR, poiLight._intensityColor);
|
||
shaderValues.setVector3(Scene3D.POINTLIGHTPOS, poiLight.transform.position);
|
||
shaderValues.setNumber(Scene3D.POINTLIGHTRANGE, poiLight.range);
|
||
shaderValues.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_POINTLIGHT);
|
||
}
|
||
else {
|
||
shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_POINTLIGHT);
|
||
}
|
||
if (this._spotLights._length > 0) {
|
||
var spotLight = this._spotLights._elements[0];
|
||
this._mainSpotLight = spotLight;
|
||
Vector3.scale(spotLight.color, spotLight._intensity, spotLight._intensityColor);
|
||
shaderValues.setVector3(Scene3D.SPOTLIGHTCOLOR, spotLight._intensityColor);
|
||
shaderValues.setVector3(Scene3D.SPOTLIGHTPOS, spotLight.transform.position);
|
||
spotLight.transform.worldMatrix.getForward(spotLight._direction);
|
||
Vector3.normalize(spotLight._direction, spotLight._direction);
|
||
shaderValues.setVector3(Scene3D.SPOTLIGHTDIRECTION, spotLight._direction);
|
||
shaderValues.setNumber(Scene3D.SPOTLIGHTRANGE, spotLight.range);
|
||
shaderValues.setNumber(Scene3D.SPOTLIGHTSPOTANGLE, spotLight.spotAngle * Math.PI / 180);
|
||
shaderValues.addDefine(Scene3DShaderDeclaration.SHADERDEFINE_SPOTLIGHT);
|
||
}
|
||
else {
|
||
shaderValues.removeDefine(Scene3DShaderDeclaration.SHADERDEFINE_SPOTLIGHT);
|
||
}
|
||
}
|
||
}
|
||
_addScript(script) {
|
||
if (script._indexInPool != -1)
|
||
return;
|
||
var scripts = this._scriptPool;
|
||
script._indexInPool = scripts.length;
|
||
scripts.push(script);
|
||
}
|
||
_removeScript(script) {
|
||
if (script._indexInPool == -1)
|
||
return;
|
||
this._scriptPool[script._indexInPool] = null;
|
||
script._indexInPool = -1;
|
||
this._needClearScriptPool = true;
|
||
}
|
||
_preRenderScript() {
|
||
var scripts = this._scriptPool;
|
||
for (var i = 0, n = scripts.length; i < n; i++) {
|
||
var script = scripts[i];
|
||
(script && script.enabled) && (script.onPreRender());
|
||
}
|
||
}
|
||
_postRenderScript() {
|
||
var scripts = this._scriptPool;
|
||
for (var i = 0, n = scripts.length; i < n; i++) {
|
||
var script = scripts[i];
|
||
(script && script.enabled) && (script.onPostRender());
|
||
}
|
||
}
|
||
_addCamera(camera) {
|
||
var index = this._binarySearchIndexInCameraPool(camera);
|
||
var order = camera._renderingOrder;
|
||
var count = this._cameraPool.length;
|
||
while (index < count && this._cameraPool[index]._renderingOrder <= order)
|
||
index++;
|
||
this._cameraPool.splice(index, 0, camera);
|
||
}
|
||
_removeCamera(camera) {
|
||
this._cameraPool.splice(this._cameraPool.indexOf(camera), 1);
|
||
}
|
||
_preCulling(context, camera, shader, replacementTag) {
|
||
var cameraCullInfo = FrustumCulling._cameraCullInfo;
|
||
cameraCullInfo.position = camera._transform.position;
|
||
cameraCullInfo.cullingMask = camera.cullingMask;
|
||
cameraCullInfo.boundFrustum = camera.boundFrustum;
|
||
cameraCullInfo.useOcclusionCulling = camera.useOcclusionCulling;
|
||
FrustumCulling.renderObjectCulling(cameraCullInfo, this, context, shader, replacementTag, false);
|
||
}
|
||
_clear(gl, state) {
|
||
var viewport = state.viewport;
|
||
var camera = state.camera;
|
||
var renderTex = camera._getRenderTexture();
|
||
var vpX, vpY;
|
||
var vpW = viewport.width;
|
||
var vpH = viewport.height;
|
||
if (camera._needInternalRenderTexture()) {
|
||
vpX = 0;
|
||
vpY = 0;
|
||
}
|
||
else {
|
||
vpX = viewport.x;
|
||
vpY = camera._getCanvasHeight() - viewport.y - vpH;
|
||
}
|
||
gl.viewport(vpX, vpY, vpW, vpH);
|
||
var flag;
|
||
var clearFlag = camera.clearFlag;
|
||
if (clearFlag === exports.CameraClearFlags.Sky && !(camera.skyRenderer._isAvailable() || this._skyRenderer._isAvailable()))
|
||
clearFlag = exports.CameraClearFlags.SolidColor;
|
||
switch (clearFlag) {
|
||
case exports.CameraClearFlags.SolidColor:
|
||
var clearColor = camera.clearColor;
|
||
gl.enable(gl.SCISSOR_TEST);
|
||
gl.scissor(vpX, vpY, vpW, vpH);
|
||
if (clearColor)
|
||
gl.clearColor(clearColor.x, clearColor.y, clearColor.z, clearColor.w);
|
||
else
|
||
gl.clearColor(0, 0, 0, 0);
|
||
if (renderTex) {
|
||
flag = gl.COLOR_BUFFER_BIT;
|
||
switch (renderTex.depthStencilFormat) {
|
||
case Laya.RenderTextureDepthFormat.DEPTH_16:
|
||
flag |= gl.DEPTH_BUFFER_BIT;
|
||
break;
|
||
case Laya.RenderTextureDepthFormat.STENCIL_8:
|
||
flag |= gl.STENCIL_BUFFER_BIT;
|
||
break;
|
||
case Laya.RenderTextureDepthFormat.DEPTHSTENCIL_24_8:
|
||
flag |= gl.DEPTH_BUFFER_BIT;
|
||
flag |= gl.STENCIL_BUFFER_BIT;
|
||
break;
|
||
}
|
||
}
|
||
else {
|
||
flag = gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT;
|
||
}
|
||
Laya.WebGLContext.setDepthMask(gl, true);
|
||
gl.clear(flag);
|
||
gl.disable(gl.SCISSOR_TEST);
|
||
break;
|
||
case exports.CameraClearFlags.Sky:
|
||
case exports.CameraClearFlags.DepthOnly:
|
||
gl.enable(gl.SCISSOR_TEST);
|
||
gl.scissor(vpX, vpY, vpW, vpH);
|
||
if (renderTex) {
|
||
switch (renderTex.depthStencilFormat) {
|
||
case Laya.RenderTextureDepthFormat.DEPTH_16:
|
||
flag = gl.DEPTH_BUFFER_BIT;
|
||
break;
|
||
case Laya.RenderTextureDepthFormat.STENCIL_8:
|
||
flag = gl.STENCIL_BUFFER_BIT;
|
||
break;
|
||
case Laya.RenderTextureDepthFormat.DEPTHSTENCIL_24_8:
|
||
flag = gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT;
|
||
break;
|
||
}
|
||
}
|
||
else {
|
||
flag = gl.DEPTH_BUFFER_BIT;
|
||
}
|
||
Laya.WebGLContext.setDepthMask(gl, true);
|
||
gl.clear(flag);
|
||
gl.disable(gl.SCISSOR_TEST);
|
||
break;
|
||
case exports.CameraClearFlags.Nothing:
|
||
break;
|
||
default:
|
||
throw new Error("Scene3D:camera clearFlag invalid.");
|
||
}
|
||
}
|
||
_renderScene(context, renderFlag) {
|
||
var camera = context.camera;
|
||
switch (renderFlag) {
|
||
case Scene3D.SCENERENDERFLAG_RENDERQPAQUE:
|
||
this._opaqueQueue._render(context);
|
||
break;
|
||
case Scene3D.SCENERENDERFLAG_SKYBOX:
|
||
if (camera.clearFlag === exports.CameraClearFlags.Sky) {
|
||
if (camera.skyRenderer._isAvailable())
|
||
camera.skyRenderer._render(context);
|
||
else if (this._skyRenderer._isAvailable())
|
||
this._skyRenderer._render(context);
|
||
}
|
||
break;
|
||
case Scene3D.SCENERENDERFLAG_RENDERTRANSPARENT:
|
||
this._transparentQueue._render(context);
|
||
if (FrustumCulling.debugFrustumCulling) {
|
||
var renderElements = this._debugTool._render._renderElements;
|
||
for (var i = 0, n = renderElements.length; i < n; i++) {
|
||
renderElements[i]._update(this, context, null, null);
|
||
renderElements[i]._render(context);
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
_parse(data, spriteMap) {
|
||
var lightMapsData = data.lightmaps;
|
||
if (lightMapsData) {
|
||
var lightMapCount = lightMapsData.length;
|
||
var lightmaps = new Array(lightMapCount);
|
||
for (var i = 0; i < lightMapCount; i++) {
|
||
var lightMap = new Lightmap();
|
||
var lightMapData = lightMapsData[i];
|
||
if (lightMapData.path) {
|
||
lightMap.lightmapColor = Laya.Loader.getRes(lightMapData.path);
|
||
}
|
||
else {
|
||
lightMap.lightmapColor = Laya.Loader.getRes(lightMapData.color.path);
|
||
if (lightMapData.direction)
|
||
lightMap.lightmapDirection = Laya.Loader.getRes(lightMapData.direction.path);
|
||
}
|
||
lightmaps[i] = lightMap;
|
||
}
|
||
this.lightmaps = lightmaps;
|
||
}
|
||
var ambientColorData = data.ambientColor;
|
||
if (ambientColorData) {
|
||
var ambCol = this.ambientColor;
|
||
ambCol.fromArray(ambientColorData);
|
||
this.ambientColor = ambCol;
|
||
}
|
||
var skyData = data.sky;
|
||
if (skyData) {
|
||
this._skyRenderer.material = Laya.Loader.getRes(skyData.material.path);
|
||
switch (skyData.mesh) {
|
||
case "SkyBox":
|
||
this._skyRenderer.mesh = SkyBox.instance;
|
||
break;
|
||
case "SkyDome":
|
||
this._skyRenderer.mesh = SkyDome.instance;
|
||
break;
|
||
default:
|
||
this.skyRenderer.mesh = SkyBox.instance;
|
||
}
|
||
}
|
||
this.enableFog = data.enableFog;
|
||
this.fogStart = data.fogStart;
|
||
this.fogRange = data.fogRange;
|
||
var fogColorData = data.fogColor;
|
||
if (fogColorData) {
|
||
var fogCol = this.fogColor;
|
||
fogCol.fromArray(fogColorData);
|
||
this.fogColor = fogCol;
|
||
}
|
||
var ambientSphericalHarmonicsData = data.ambientSphericalHarmonics;
|
||
if (ambientSphericalHarmonicsData) {
|
||
var ambientSH = this.ambientSphericalHarmonics;
|
||
for (var i = 0; i < 3; i++) {
|
||
var off = i * 9;
|
||
ambientSH.setCoefficients(i, ambientSphericalHarmonicsData[off], ambientSphericalHarmonicsData[off + 1], ambientSphericalHarmonicsData[off + 2], ambientSphericalHarmonicsData[off + 3], ambientSphericalHarmonicsData[off + 4], ambientSphericalHarmonicsData[off + 5], ambientSphericalHarmonicsData[off + 6], ambientSphericalHarmonicsData[off + 7], ambientSphericalHarmonicsData[off + 8]);
|
||
}
|
||
this.ambientSphericalHarmonics = ambientSH;
|
||
}
|
||
var reflectionData = data.reflection;
|
||
(reflectionData != undefined) && (this.reflection = Laya.Loader.getRes(reflectionData));
|
||
var reflectionDecodingFormatData = data.reflectionDecodingFormat;
|
||
(reflectionDecodingFormatData != undefined) && (this.reflectionDecodingFormat = reflectionDecodingFormatData);
|
||
var ambientModeData = data.ambientMode;
|
||
(ambientModeData != undefined) && (this.ambientMode = ambientModeData);
|
||
var ambientSphericalHarmonicsIntensityData = data.ambientSphericalHarmonicsIntensity;
|
||
(ambientSphericalHarmonicsIntensityData != undefined) && (this.ambientSphericalHarmonicsIntensity = ambientSphericalHarmonicsIntensityData);
|
||
var reflectionIntensityData = data.reflectionIntensity;
|
||
(reflectionIntensityData != undefined) && (this.reflectionIntensity = reflectionIntensityData);
|
||
}
|
||
_addRenderObject(render) {
|
||
if (this._octree && render._supportOctree) {
|
||
this._octree.add(render);
|
||
}
|
||
else {
|
||
this._renders.add(render);
|
||
}
|
||
render._addReflectionProbeUpdate();
|
||
}
|
||
_removeRenderObject(render) {
|
||
if (this._octree && render._supportOctree) {
|
||
this._octree.remove(render);
|
||
}
|
||
else {
|
||
this._renders.remove(render);
|
||
}
|
||
}
|
||
_getRenderQueue(index) {
|
||
if (index <= 2500)
|
||
return this._opaqueQueue;
|
||
else
|
||
return this._transparentQueue;
|
||
}
|
||
_clearRenderQueue() {
|
||
this._opaqueQueue.clear();
|
||
this._transparentQueue.clear();
|
||
var staticBatchManagers = StaticBatchManager._managers;
|
||
for (var i = 0, n = staticBatchManagers.length; i < n; i++)
|
||
staticBatchManagers[i]._clear();
|
||
var dynamicBatchManagers = DynamicBatchManager._managers;
|
||
for (var i = 0, n = dynamicBatchManagers.length; i < n; i++)
|
||
dynamicBatchManagers[i]._clear();
|
||
}
|
||
destroy(destroyChild = true) {
|
||
if (this.destroyed)
|
||
return;
|
||
super.destroy(destroyChild);
|
||
this._skyRenderer.destroy();
|
||
this._skyRenderer = null;
|
||
this._directionLights = null;
|
||
this._pointLights = null;
|
||
this._spotLights = null;
|
||
this._alternateLights = null;
|
||
this._shaderValues = null;
|
||
this._renders.clearElement();
|
||
this._animatorPool.clearElement();
|
||
this._renders = null;
|
||
this._animatorPool = null;
|
||
this._cameraPool = null;
|
||
this._octree = null;
|
||
this._physicsSimulation && this._physicsSimulation._destroy();
|
||
this._reflection._removeReference();
|
||
this._reflection = null;
|
||
var maps = this._lightmaps;
|
||
if (maps) {
|
||
for (var i = 0, n = maps.length; i < n; i++) {
|
||
var map = maps[i];
|
||
map.lightmapColor && map.lightmapColor._removeReference();
|
||
map.lightmapDirection && map.lightmapDirection._removeReference();
|
||
}
|
||
}
|
||
this._lightmaps = null;
|
||
this._reflectionProbeManager.destroy();
|
||
Laya.Loader.clearRes(this.url);
|
||
}
|
||
render(ctx) {
|
||
ctx._curSubmit = Laya.SubmitBase.RENDERBASE;
|
||
this._children.length > 0 && ctx.addRenderObject(this);
|
||
}
|
||
renderSubmit() {
|
||
Laya.PerformancePlugin.begainSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D);
|
||
this._prepareSceneToRender();
|
||
var i, n, n1;
|
||
Laya.PerformancePlugin.begainSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D_RENDER);
|
||
for (i = 0, n = this._cameraPool.length, n1 = n - 1; i < n; i++) {
|
||
if (Laya.Render.supportWebGLPlusRendering)
|
||
ShaderData.setRuntimeValueMode((i == n1) ? true : false);
|
||
var camera = this._cameraPool[i];
|
||
camera.enableRender && camera.render();
|
||
}
|
||
Laya.PerformancePlugin.endSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D_RENDER);
|
||
Laya.Context.set2DRenderConfig();
|
||
Laya.PerformancePlugin.endSample(Laya.PerformancePlugin.PERFORMANCE_LAYA_3D);
|
||
return 1;
|
||
}
|
||
getRenderType() {
|
||
return 0;
|
||
}
|
||
releaseRender() {
|
||
}
|
||
reUse(context, pos) {
|
||
return 0;
|
||
}
|
||
setGlobalShaderValue(name, shaderDataType, value) {
|
||
var shaderOffset = Shader3D.propertyNameToID(name);
|
||
switch (shaderDataType) {
|
||
case exports.ShaderDataType.Int:
|
||
this._shaderValues.setInt(shaderOffset, value);
|
||
break;
|
||
case exports.ShaderDataType.Number:
|
||
this._shaderValues.setNumber(shaderOffset, value);
|
||
break;
|
||
case exports.ShaderDataType.Bool:
|
||
this._shaderValues.setBool(shaderOffset, value);
|
||
break;
|
||
case exports.ShaderDataType.Matrix4x4:
|
||
this._shaderValues.setMatrix4x4(shaderOffset, value);
|
||
break;
|
||
case exports.ShaderDataType.Quaternion:
|
||
this._shaderValues.setQuaternion(shaderOffset, value);
|
||
break;
|
||
case exports.ShaderDataType.Texture:
|
||
this._shaderValues.setTexture(shaderOffset, value);
|
||
break;
|
||
case exports.ShaderDataType.Vector4:
|
||
this._shaderValues.setVector(shaderOffset, value);
|
||
break;
|
||
case exports.ShaderDataType.Vector2:
|
||
this._shaderValues.setVector2(shaderOffset, value);
|
||
break;
|
||
case exports.ShaderDataType.Vector3:
|
||
this._shaderValues.setVector3(shaderOffset, value);
|
||
break;
|
||
case exports.ShaderDataType.Buffer:
|
||
this._shaderValues.setBuffer(shaderOffset, value);
|
||
break;
|
||
}
|
||
}
|
||
get customReflection() {
|
||
return this._reflection;
|
||
}
|
||
set customReflection(value) {
|
||
if (this._reflection != value) {
|
||
value._addReference();
|
||
this._reflectionProbeManager.sceneReflectionProbe = value;
|
||
this._reflection = value;
|
||
}
|
||
}
|
||
get reflectionMode() {
|
||
return this._reflectionMode;
|
||
}
|
||
set reflectionMode(value) {
|
||
this._reflectionMode = value;
|
||
}
|
||
setlightmaps(value) {
|
||
var maps = this._lightmaps;
|
||
for (var i = 0, n = maps.length; i < n; i++)
|
||
maps[i].lightmapColor._removeReference();
|
||
if (value) {
|
||
var count = value.length;
|
||
maps.length = count;
|
||
for (i = 0; i < count; i++) {
|
||
var lightMap = value[i];
|
||
lightMap._addReference();
|
||
(maps[i]) || (maps[i] = new Lightmap());
|
||
maps[i].lightmapColor = lightMap;
|
||
}
|
||
}
|
||
else {
|
||
throw new Error("Scene3D: value value can't be null.");
|
||
}
|
||
}
|
||
getlightmaps() {
|
||
var lightmapColors = new Array(this._lightmaps.length);
|
||
for (var i = 0; i < this._lightmaps.length; i++) {
|
||
lightmapColors[i] = this._lightmaps[i].lightmapColor;
|
||
}
|
||
return lightmapColors;
|
||
}
|
||
}
|
||
Scene3D._shadowCasterPass = new ShadowCasterPass();
|
||
Scene3D.HIERARCHY = "HIERARCHY";
|
||
Scene3D.octreeCulling = false;
|
||
Scene3D.octreeInitialSize = 64.0;
|
||
Scene3D.octreeInitialCenter = new Vector3(0, 0, 0);
|
||
Scene3D.octreeMinNodeSize = 2.0;
|
||
Scene3D.octreeLooseness = 1.25;
|
||
Scene3D.REFLECTIONMODE_SKYBOX = 0;
|
||
Scene3D.REFLECTIONMODE_CUSTOM = 1;
|
||
Scene3D.SCENERENDERFLAG_RENDERQPAQUE = 0;
|
||
Scene3D.SCENERENDERFLAG_SKYBOX = 1;
|
||
Scene3D.SCENERENDERFLAG_RENDERTRANSPARENT = 2;
|
||
Scene3D.FOGCOLOR = Shader3D.propertyNameToID("u_FogColor");
|
||
Scene3D.FOGSTART = Shader3D.propertyNameToID("u_FogStart");
|
||
Scene3D.FOGRANGE = Shader3D.propertyNameToID("u_FogRange");
|
||
Scene3D.DIRECTIONLIGHTCOUNT = Shader3D.propertyNameToID("u_DirationLightCount");
|
||
Scene3D.LIGHTBUFFER = Shader3D.propertyNameToID("u_LightBuffer");
|
||
Scene3D.CLUSTERBUFFER = Shader3D.propertyNameToID("u_LightClusterBuffer");
|
||
Scene3D.SUNLIGHTDIRECTION = Shader3D.propertyNameToID("u_SunLight.direction");
|
||
Scene3D.SUNLIGHTDIRCOLOR = Shader3D.propertyNameToID("u_SunLight.color");
|
||
Scene3D.AMBIENTSHAR = Shader3D.propertyNameToID("u_AmbientSHAr");
|
||
Scene3D.AMBIENTSHAG = Shader3D.propertyNameToID("u_AmbientSHAg");
|
||
Scene3D.AMBIENTSHAB = Shader3D.propertyNameToID("u_AmbientSHAb");
|
||
Scene3D.AMBIENTSHBR = Shader3D.propertyNameToID("u_AmbientSHBr");
|
||
Scene3D.AMBIENTSHBG = Shader3D.propertyNameToID("u_AmbientSHBg");
|
||
Scene3D.AMBIENTSHBB = Shader3D.propertyNameToID("u_AmbientSHBb");
|
||
Scene3D.AMBIENTSHC = Shader3D.propertyNameToID("u_AmbientSHC");
|
||
Scene3D.LIGHTDIRECTION = Shader3D.propertyNameToID("u_DirectionLight.direction");
|
||
Scene3D.LIGHTDIRCOLOR = Shader3D.propertyNameToID("u_DirectionLight.color");
|
||
Scene3D.POINTLIGHTPOS = Shader3D.propertyNameToID("u_PointLight.position");
|
||
Scene3D.POINTLIGHTRANGE = Shader3D.propertyNameToID("u_PointLight.range");
|
||
Scene3D.POINTLIGHTATTENUATION = Shader3D.propertyNameToID("u_PointLight.attenuation");
|
||
Scene3D.POINTLIGHTCOLOR = Shader3D.propertyNameToID("u_PointLight.color");
|
||
Scene3D.SPOTLIGHTPOS = Shader3D.propertyNameToID("u_SpotLight.position");
|
||
Scene3D.SPOTLIGHTDIRECTION = Shader3D.propertyNameToID("u_SpotLight.direction");
|
||
Scene3D.SPOTLIGHTSPOTANGLE = Shader3D.propertyNameToID("u_SpotLight.spot");
|
||
Scene3D.SPOTLIGHTRANGE = Shader3D.propertyNameToID("u_SpotLight.range");
|
||
Scene3D.SPOTLIGHTCOLOR = Shader3D.propertyNameToID("u_SpotLight.color");
|
||
Scene3D.AMBIENTCOLOR = Shader3D.propertyNameToID("u_AmbientColor");
|
||
Scene3D.TIME = Shader3D.propertyNameToID("u_Time");
|
||
Scene3D._configDefineValues = new DefineDatas();
|
||
|
||
class ShaderPass extends Laya.ShaderCompile {
|
||
constructor(owner, vs, ps, stateMap) {
|
||
super(vs, ps, null);
|
||
this._cacheSharders = {};
|
||
this._cacheShaderHierarchy = 1;
|
||
this._renderState = new RenderState();
|
||
this._validDefine = new DefineDatas();
|
||
this._tags = {};
|
||
this._owner = owner;
|
||
this._stateMap = stateMap;
|
||
for (var k in this.defs)
|
||
this._validDefine.add(Shader3D.getDefineByName(k));
|
||
}
|
||
get renderState() {
|
||
return this._renderState;
|
||
}
|
||
_compileToTree(parent, lines, start, includefiles, defs) {
|
||
var node, preNode;
|
||
var text, name, fname;
|
||
var ofs, words, noUseNode;
|
||
var i, n, j;
|
||
for (i = start; i < lines.length; i++) {
|
||
text = lines[i];
|
||
if (text.length < 1)
|
||
continue;
|
||
ofs = text.indexOf("//");
|
||
if (ofs === 0)
|
||
continue;
|
||
if (ofs >= 0)
|
||
text = text.substr(0, ofs);
|
||
node = noUseNode || new Laya.ShaderNode(includefiles);
|
||
noUseNode = null;
|
||
node.text = text;
|
||
node.noCompile = true;
|
||
if ((ofs = text.indexOf("#")) >= 0) {
|
||
name = "#";
|
||
for (j = ofs + 1, n = text.length; j < n; j++) {
|
||
var c = text.charAt(j);
|
||
if (c === ' ' || c === '\t' || c === '?')
|
||
break;
|
||
name += c;
|
||
}
|
||
node.name = name;
|
||
switch (name) {
|
||
case "#ifdef":
|
||
case "#ifndef":
|
||
node.src = text;
|
||
node.noCompile = text.match(/[!&|()=<>]/) != null;
|
||
if (!node.noCompile) {
|
||
words = text.replace(/^\s*/, '').split(/\s+/);
|
||
node.setCondition(words[1], name === "#ifdef" ? Laya.ShaderCompile.IFDEF_YES : Laya.ShaderCompile.IFDEF_ELSE);
|
||
node.text = "//" + node.text;
|
||
}
|
||
else {
|
||
console.log("function():Boolean{return " + text.substr(ofs + node.name.length) + "}");
|
||
}
|
||
node.setParent(parent);
|
||
parent = node;
|
||
if (defs) {
|
||
words = text.substr(j).split(Laya.ShaderCompile._splitToWordExps3);
|
||
for (j = 0; j < words.length; j++) {
|
||
text = words[j];
|
||
text.length && (defs[text] = true);
|
||
}
|
||
}
|
||
continue;
|
||
case "#if":
|
||
case "#elif":
|
||
node.src = text;
|
||
node.noCompile = true;
|
||
if (name == "#elif") {
|
||
parent = parent.parent;
|
||
preNode = parent.childs[parent.childs.length - 1];
|
||
preNode.text = preNode.src;
|
||
preNode.noCompile = true;
|
||
preNode.condition = null;
|
||
}
|
||
node.setParent(parent);
|
||
parent = node;
|
||
if (defs) {
|
||
words = text.substr(j).split(Laya.ShaderCompile._splitToWordExps3);
|
||
for (j = 0; j < words.length; j++) {
|
||
text = words[j];
|
||
text.length && text != "defined" && (defs[text] = true);
|
||
}
|
||
}
|
||
continue;
|
||
case "#else":
|
||
node.src = text;
|
||
parent = parent.parent;
|
||
preNode = parent.childs[parent.childs.length - 1];
|
||
node.noCompile = preNode.noCompile;
|
||
if (!node.noCompile) {
|
||
node.condition = preNode.condition;
|
||
node.conditionType = preNode.conditionType == Laya.ShaderCompile.IFDEF_YES ? Laya.ShaderCompile.IFDEF_ELSE : Laya.ShaderCompile.IFDEF_YES;
|
||
node.text = "//" + node.text + " " + preNode.text + " " + node.conditionType;
|
||
}
|
||
node.setParent(parent);
|
||
parent = node;
|
||
continue;
|
||
case "#endif":
|
||
parent = parent.parent;
|
||
preNode = parent.childs[parent.childs.length - 1];
|
||
node.noCompile = preNode.noCompile;
|
||
if (!node.noCompile) {
|
||
node.text = "//" + node.text;
|
||
}
|
||
node.setParent(parent);
|
||
continue;
|
||
case "#include":
|
||
words = Laya.ShaderCompile.splitToWords(text, null);
|
||
var inlcudeFile = Laya.ShaderCompile.includes[words[1]];
|
||
if (!inlcudeFile) {
|
||
throw "ShaderCompile error no this include file:" + words[1];
|
||
}
|
||
if ((ofs = words[0].indexOf("?")) < 0) {
|
||
node.setParent(parent);
|
||
text = inlcudeFile.getWith(words[2] == 'with' ? words[3] : null);
|
||
this._compileToTree(node, text.split('\n'), 0, includefiles, defs);
|
||
node.text = "";
|
||
continue;
|
||
}
|
||
node.setCondition(words[0].substr(ofs + 1), Laya.ShaderCompile.IFDEF_YES);
|
||
node.text = inlcudeFile.getWith(words[2] == 'with' ? words[3] : null);
|
||
break;
|
||
case "#import":
|
||
words = Laya.ShaderCompile.splitToWords(text, null);
|
||
fname = words[1];
|
||
includefiles.push({ node: node, file: Laya.ShaderCompile.includes[fname], ofs: node.text.length });
|
||
continue;
|
||
}
|
||
}
|
||
else {
|
||
preNode = parent.childs[parent.childs.length - 1];
|
||
if (preNode && !preNode.name) {
|
||
includefiles.length > 0 && Laya.ShaderCompile.splitToWords(text, preNode);
|
||
noUseNode = node;
|
||
preNode.text += "\n" + text;
|
||
continue;
|
||
}
|
||
includefiles.length > 0 && Laya.ShaderCompile.splitToWords(text, node);
|
||
}
|
||
node.setParent(parent);
|
||
}
|
||
}
|
||
_resizeCacheShaderMap(cacheMap, hierarchy, resizeLength) {
|
||
var end = this._cacheShaderHierarchy - 1;
|
||
if (hierarchy == end) {
|
||
for (var k in cacheMap) {
|
||
var shader = cacheMap[k];
|
||
for (var i = 0, n = resizeLength - end; i < n; i++) {
|
||
if (i == n - 1)
|
||
cacheMap[0] = shader;
|
||
else
|
||
cacheMap = cacheMap[i == 0 ? k : 0] = {};
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
++hierarchy;
|
||
for (var k in cacheMap)
|
||
this._resizeCacheShaderMap(cacheMap[k], hierarchy, resizeLength);
|
||
}
|
||
}
|
||
_addDebugShaderVariantCollection(compileDefine, outDebugDefines, outDebugDefineMask) {
|
||
var dbugShaderVariantInfo = Shader3D._debugShaderVariantInfo;
|
||
var debugSubShader = this._owner;
|
||
var debugShader = debugSubShader._owner;
|
||
var mask = compileDefine._mask;
|
||
Shader3D._getNamesByDefineData(compileDefine, outDebugDefines);
|
||
outDebugDefineMask.length = mask.length;
|
||
for (var i = 0, n = mask.length; i < n; i++)
|
||
outDebugDefineMask[i] = mask[i];
|
||
if (dbugShaderVariantInfo)
|
||
dbugShaderVariantInfo.setValue(debugShader, debugShader._subShaders.indexOf(debugSubShader), debugSubShader._passes.indexOf(this), outDebugDefines);
|
||
else
|
||
Shader3D._debugShaderVariantInfo = dbugShaderVariantInfo = new ShaderVariant(debugShader, debugShader._subShaders.indexOf(debugSubShader), debugSubShader._passes.indexOf(this), outDebugDefines);
|
||
Shader3D.debugShaderVariantCollection.add(dbugShaderVariantInfo);
|
||
}
|
||
withCompile(compileDefine) {
|
||
var debugDefineString = ShaderPass._debugDefineString;
|
||
var debugDefineMask = ShaderPass._debugDefineMask;
|
||
var debugMaskLength;
|
||
compileDefine._intersectionDefineDatas(this._validDefine);
|
||
if (Shader3D.debugMode) {
|
||
debugMaskLength = compileDefine._length;
|
||
this._addDebugShaderVariantCollection(compileDefine, debugDefineString, debugDefineMask);
|
||
}
|
||
compileDefine.addDefineDatas(Scene3D._configDefineValues);
|
||
var cacheShaders = this._cacheSharders;
|
||
var maskLength = compileDefine._length;
|
||
if (maskLength > this._cacheShaderHierarchy) {
|
||
this._resizeCacheShaderMap(cacheShaders, 0, maskLength);
|
||
this._cacheShaderHierarchy = maskLength;
|
||
}
|
||
var mask = compileDefine._mask;
|
||
var endIndex = compileDefine._length - 1;
|
||
var maxEndIndex = this._cacheShaderHierarchy - 1;
|
||
for (var i = 0; i < maxEndIndex; i++) {
|
||
var subMask = endIndex < i ? 0 : mask[i];
|
||
var subCacheShaders = cacheShaders[subMask];
|
||
(subCacheShaders) || (cacheShaders[subMask] = subCacheShaders = {});
|
||
cacheShaders = subCacheShaders;
|
||
}
|
||
var cacheKey = endIndex < maxEndIndex ? 0 : mask[maxEndIndex];
|
||
var shader = cacheShaders[cacheKey];
|
||
if (shader)
|
||
return shader;
|
||
var defineString = ShaderPass._defineString;
|
||
Shader3D._getNamesByDefineData(compileDefine, defineString);
|
||
var config = Config3D._config;
|
||
var clusterSlices = config.lightClusterCount;
|
||
var defMap = {};
|
||
var vertexHead;
|
||
var fragmentHead;
|
||
var defineStr = "";
|
||
if (Laya.WebGL._isWebGL2) {
|
||
vertexHead =
|
||
`#version 300 es\n
|
||
#define attribute in
|
||
#define varying out
|
||
#define texture2D texture\n`;
|
||
fragmentHead =
|
||
`#version 300 es\n
|
||
#define varying in
|
||
out highp vec4 pc_fragColor;
|
||
#define gl_FragColor pc_fragColor
|
||
#define gl_FragDepthEXT gl_FragDepth
|
||
#define texture2D texture
|
||
#define textureCube texture
|
||
#define texture2DProj textureProj
|
||
#define texture2DLodEXT textureLod
|
||
#define texture2DProjLodEXT textureProjLod
|
||
#define textureCubeLodEXT textureLod
|
||
#define texture2DGradEXT textureGrad
|
||
#define texture2DProjGradEXT textureProjGrad
|
||
#define textureCubeGradEXT textureGrad\n`;
|
||
}
|
||
else {
|
||
vertexHead = "";
|
||
fragmentHead =
|
||
`#ifdef GL_EXT_shader_texture_lod
|
||
#extension GL_EXT_shader_texture_lod : enable
|
||
#endif
|
||
#if !defined(GL_EXT_shader_texture_lod)
|
||
#define texture1DLodEXT texture1D
|
||
#define texture2DLodEXT texture2D
|
||
#define texture2DProjLodEXT texture2DProj
|
||
#define texture3DLodEXT texture3D
|
||
#define textureCubeLodEXT textureCube
|
||
#endif\n`;
|
||
}
|
||
defineStr += "#define MAX_LIGHT_COUNT " + config.maxLightCount + "\n";
|
||
defineStr += "#define MAX_LIGHT_COUNT_PER_CLUSTER " + config._maxAreaLightCountPerClusterAverage + "\n";
|
||
defineStr += "#define CLUSTER_X_COUNT " + clusterSlices.x + "\n";
|
||
defineStr += "#define CLUSTER_Y_COUNT " + clusterSlices.y + "\n";
|
||
defineStr += "#define CLUSTER_Z_COUNT " + clusterSlices.z + "\n";
|
||
defineStr += "#define SHADER_CAPAILITY_LEVEL " + Laya.SystemUtils._shaderCapailityLevel + "\n";
|
||
for (var i = 0, n = defineString.length; i < n; i++) {
|
||
var def = defineString[i];
|
||
defineStr += "#define " + def + "\n";
|
||
defMap[def] = true;
|
||
}
|
||
var vs = this._VS.toscript(defMap, []);
|
||
var vsVersion = '';
|
||
if (vs[0].indexOf('#version') == 0) {
|
||
vsVersion = vs[0] + '\n';
|
||
vs.shift();
|
||
}
|
||
var ps = this._PS.toscript(defMap, []);
|
||
var psVersion = '';
|
||
if (ps[0].indexOf('#version') == 0) {
|
||
psVersion = ps[0] + '\n';
|
||
ps.shift();
|
||
}
|
||
shader = new ShaderInstance(vsVersion + vertexHead + defineStr + vs.join('\n'), psVersion + fragmentHead + defineStr + ps.join('\n'), this._owner._attributeMap, this._owner._uniformMap || this._owner._owner._uniformMap, this);
|
||
cacheShaders[cacheKey] = shader;
|
||
if (Shader3D.debugMode) {
|
||
var defStr = "";
|
||
var defMask = "";
|
||
for (var i = 0, n = debugMaskLength; i < n; i++)
|
||
(i == n - 1) ? defMask += debugDefineMask[i] : defMask += debugDefineMask[i] + ",";
|
||
for (var i = 0, n = debugDefineString.length; i < n; i++)
|
||
(i == n - 1) ? defStr += debugDefineString[i] : defStr += debugDefineString[i] + ",";
|
||
console.log("%cLayaAir: Shader Compile Information---ShaderName:" + this._owner._owner._name + " SubShaderIndex:" + this._owner._owner._subShaders.indexOf(this._owner) + " PassIndex:" + this._owner._passes.indexOf(this) + " DefineMask:[" + defMask + "]" + " DefineNames:[" + defStr + "]", "color:green");
|
||
}
|
||
return shader;
|
||
}
|
||
setTag(key, value) {
|
||
if (value)
|
||
this._tags[key] = value;
|
||
else
|
||
delete this._tags[key];
|
||
}
|
||
getTag(key) {
|
||
return this._tags[key];
|
||
}
|
||
}
|
||
ShaderPass._defineString = [];
|
||
ShaderPass._debugDefineString = [];
|
||
ShaderPass._debugDefineMask = [];
|
||
|
||
class SubShader {
|
||
constructor(attributeMap, uniformMap) {
|
||
this._flags = {};
|
||
this._passes = [];
|
||
this._attributeMap = attributeMap;
|
||
this._uniformMap = uniformMap;
|
||
}
|
||
setFlag(key, value) {
|
||
if (value)
|
||
this._flags[key] = value;
|
||
else
|
||
delete this._flags[key];
|
||
}
|
||
getFlag(key) {
|
||
return this._flags[key];
|
||
}
|
||
addShaderPass(vs, ps, stateMap = null, pipelineMode = "Forward") {
|
||
var shaderPass = new ShaderPass(this, vs, ps, stateMap);
|
||
shaderPass._pipelineMode = pipelineMode;
|
||
this._passes.push(shaderPass);
|
||
return shaderPass;
|
||
}
|
||
}
|
||
|
||
(function (PBRSpecularSmoothnessSource) {
|
||
PBRSpecularSmoothnessSource[PBRSpecularSmoothnessSource["SpecularTextureAlpha"] = 0] = "SpecularTextureAlpha";
|
||
PBRSpecularSmoothnessSource[PBRSpecularSmoothnessSource["AlbedoTextureAlpha"] = 1] = "AlbedoTextureAlpha";
|
||
})(exports.PBRSpecularSmoothnessSource || (exports.PBRSpecularSmoothnessSource = {}));
|
||
class PBRSpecularMaterial extends PBRMaterial {
|
||
constructor() {
|
||
super();
|
||
this.setShaderName("PBRSpecular");
|
||
this._shaderValues.setVector(PBRSpecularMaterial.SPECULARCOLOR, new Vector4(0.2, 0.2, 0.2, 1.0));
|
||
}
|
||
static __init__() {
|
||
PBRSpecularMaterial.SHADERDEFINE_SPECULARGLOSSTEXTURE = Shader3D.getDefineByName("SPECULARGLOSSTEXTURE");
|
||
PBRSpecularMaterial.SHADERDEFINE_SMOOTHNESSSOURCE_ALBEDOTEXTURE_ALPHA = Shader3D.getDefineByName("SMOOTHNESSSOURCE_ALBEDOTEXTURE_ALPHA");
|
||
var attributeMap = {
|
||
'a_Position': VertexMesh.MESH_POSITION0,
|
||
'a_Normal': VertexMesh.MESH_NORMAL0,
|
||
'a_Tangent0': VertexMesh.MESH_TANGENT0,
|
||
'a_Texcoord0': VertexMesh.MESH_TEXTURECOORDINATE0,
|
||
'a_Texcoord1': VertexMesh.MESH_TEXTURECOORDINATE1,
|
||
'a_BoneWeights': VertexMesh.MESH_BLENDWEIGHT0,
|
||
'a_BoneIndices': VertexMesh.MESH_BLENDINDICES0,
|
||
'a_WorldMat': VertexMesh.MESH_WORLDMATRIX_ROW0,
|
||
'a_SimpleTextureParams': VertexMesh.MESH_SIMPLEANIMATOR
|
||
};
|
||
var uniformMap = {
|
||
'u_Bones': Shader3D.PERIOD_CUSTOM,
|
||
'u_MvpMatrix': Shader3D.PERIOD_SPRITE,
|
||
'u_WorldMat': Shader3D.PERIOD_SPRITE,
|
||
'u_LightmapScaleOffset': Shader3D.PERIOD_SPRITE,
|
||
'u_LightMap': Shader3D.PERIOD_SPRITE,
|
||
'u_LightMapDirection': Shader3D.PERIOD_SPRITE,
|
||
'u_SimpleAnimatorTexture': Shader3D.PERIOD_SPRITE,
|
||
'u_SimpleAnimatorParams': Shader3D.PERIOD_SPRITE,
|
||
'u_SimpleAnimatorTextureSize': Shader3D.PERIOD_SPRITE,
|
||
'u_ReflectCubeHDRParams': Shader3D.PERIOD_SPRITE,
|
||
'u_ReflectTexture': Shader3D.PERIOD_SPRITE,
|
||
'u_SpecCubeProbePosition': Shader3D.PERIOD_SPRITE,
|
||
'u_SpecCubeBoxMax': Shader3D.PERIOD_SPRITE,
|
||
'u_SpecCubeBoxMin': Shader3D.PERIOD_SPRITE,
|
||
'u_CameraPos': Shader3D.PERIOD_CAMERA,
|
||
'u_View': Shader3D.PERIOD_CAMERA,
|
||
'u_ProjectionParams': Shader3D.PERIOD_CAMERA,
|
||
'u_Viewport': Shader3D.PERIOD_CAMERA,
|
||
'u_ViewProjection': Shader3D.PERIOD_CAMERA,
|
||
'u_AlphaTestValue': Shader3D.PERIOD_MATERIAL,
|
||
'u_AlbedoColor': Shader3D.PERIOD_MATERIAL,
|
||
'u_EmissionColor': Shader3D.PERIOD_MATERIAL,
|
||
'u_AlbedoTexture': Shader3D.PERIOD_MATERIAL,
|
||
'u_NormalTexture': Shader3D.PERIOD_MATERIAL,
|
||
'u_ParallaxTexture': Shader3D.PERIOD_MATERIAL,
|
||
'u_OcclusionTexture': Shader3D.PERIOD_MATERIAL,
|
||
'u_EmissionTexture': Shader3D.PERIOD_MATERIAL,
|
||
'u_Smoothness': Shader3D.PERIOD_MATERIAL,
|
||
'u_SmoothnessScale': Shader3D.PERIOD_MATERIAL,
|
||
'u_occlusionStrength': Shader3D.PERIOD_MATERIAL,
|
||
'u_NormalScale': Shader3D.PERIOD_MATERIAL,
|
||
'u_ParallaxScale': Shader3D.PERIOD_MATERIAL,
|
||
'u_TilingOffset': Shader3D.PERIOD_MATERIAL,
|
||
'u_SpecGlossTexture': Shader3D.PERIOD_MATERIAL,
|
||
'u_SpecularColor': Shader3D.PERIOD_MATERIAL,
|
||
'u_AmbientColor': Shader3D.PERIOD_SCENE,
|
||
'u_FogStart': Shader3D.PERIOD_SCENE,
|
||
'u_FogRange': Shader3D.PERIOD_SCENE,
|
||
'u_FogColor': Shader3D.PERIOD_SCENE,
|
||
'u_DirationLightCount': Shader3D.PERIOD_SCENE,
|
||
'u_LightBuffer': Shader3D.PERIOD_SCENE,
|
||
'u_LightClusterBuffer': Shader3D.PERIOD_SCENE,
|
||
'u_ShadowBias': Shader3D.PERIOD_SCENE,
|
||
'u_ShadowLightDirection': Shader3D.PERIOD_SCENE,
|
||
'u_ShadowMap': Shader3D.PERIOD_SCENE,
|
||
'u_ShadowParams': Shader3D.PERIOD_SCENE,
|
||
'u_ShadowSplitSpheres': Shader3D.PERIOD_SCENE,
|
||
'u_ShadowMatrices': Shader3D.PERIOD_SCENE,
|
||
'u_ShadowMapSize': Shader3D.PERIOD_SCENE,
|
||
'u_SpotShadowMap': Shader3D.PERIOD_SCENE,
|
||
'u_SpotViewProjectMatrix': Shader3D.PERIOD_SCENE,
|
||
'u_ShadowLightPosition': Shader3D.PERIOD_SCENE,
|
||
'u_AmbientSHAr': Shader3D.PERIOD_SCENE,
|
||
'u_AmbientSHAg': Shader3D.PERIOD_SCENE,
|
||
'u_AmbientSHAb': Shader3D.PERIOD_SCENE,
|
||
'u_AmbientSHBr': Shader3D.PERIOD_SCENE,
|
||
'u_AmbientSHBg': Shader3D.PERIOD_SCENE,
|
||
'u_AmbientSHBb': Shader3D.PERIOD_SCENE,
|
||
'u_AmbientSHC': Shader3D.PERIOD_SCENE,
|
||
'u_DirectionLight.direction': Shader3D.PERIOD_SCENE,
|
||
'u_DirectionLight.color': Shader3D.PERIOD_SCENE,
|
||
'u_PointLight.position': Shader3D.PERIOD_SCENE,
|
||
'u_PointLight.range': Shader3D.PERIOD_SCENE,
|
||
'u_PointLight.color': Shader3D.PERIOD_SCENE,
|
||
'u_SpotLight.position': Shader3D.PERIOD_SCENE,
|
||
'u_SpotLight.direction': Shader3D.PERIOD_SCENE,
|
||
'u_SpotLight.range': Shader3D.PERIOD_SCENE,
|
||
'u_SpotLight.spot': Shader3D.PERIOD_SCENE,
|
||
'u_SpotLight.color': Shader3D.PERIOD_SCENE
|
||
};
|
||
var stateMap = {
|
||
's_Cull': Shader3D.RENDER_STATE_CULL,
|
||
's_Blend': Shader3D.RENDER_STATE_BLEND,
|
||
's_BlendSrc': Shader3D.RENDER_STATE_BLEND_SRC,
|
||
's_BlendDst': Shader3D.RENDER_STATE_BLEND_DST,
|
||
's_DepthTest': Shader3D.RENDER_STATE_DEPTH_TEST,
|
||
's_DepthWrite': Shader3D.RENDER_STATE_DEPTH_WRITE
|
||
};
|
||
var shader = Shader3D.add("PBRSpecular", attributeMap, uniformMap, true, true);
|
||
var subShader = new SubShader(attributeMap, uniformMap);
|
||
shader.addSubShader(subShader);
|
||
subShader.addShaderPass(PBRVS, PBRPS, stateMap, "Forward");
|
||
subShader.addShaderPass(PBRShadowCasterVS, PBRShadowCasterPS, stateMap, "ShadowCaster");
|
||
subShader.addShaderPass(DepthNormalsTextureVS, DepthNormalsTextureFS, stateMap, "DepthNormal");
|
||
}
|
||
get specularTexture() {
|
||
return this._shaderValues.getTexture(PBRSpecularMaterial.SPECULARTEXTURE);
|
||
}
|
||
set specularTexture(value) {
|
||
if (value)
|
||
this._shaderValues.addDefine(PBRSpecularMaterial.SHADERDEFINE_SPECULARGLOSSTEXTURE);
|
||
else
|
||
this._shaderValues.removeDefine(PBRSpecularMaterial.SHADERDEFINE_SPECULARGLOSSTEXTURE);
|
||
this._shaderValues.setTexture(PBRSpecularMaterial.SPECULARTEXTURE, value);
|
||
}
|
||
get specularColor() {
|
||
return this._shaderValues.getVector(PBRSpecularMaterial.SPECULARCOLOR);
|
||
}
|
||
set specularColor(value) {
|
||
this._shaderValues.setVector(PBRSpecularMaterial.SPECULARCOLOR, value);
|
||
}
|
||
clone() {
|
||
var dest = new PBRSpecularMaterial();
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
}
|
||
PBRSpecularMaterial.SPECULARTEXTURE = Shader3D.propertyNameToID("u_SpecGlossTexture");
|
||
PBRSpecularMaterial.SPECULARCOLOR = Shader3D.propertyNameToID("u_SpecularColor");
|
||
|
||
var PBRPS$1 = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n\tprecision highp int;\r\n#else\r\n\tprecision mediump float;\r\n\tprecision mediump int;\r\n#endif\r\n\r\n#include \"Lighting.glsl\";\r\n#include \"Shadow.glsl\"\r\n#include \"PBRFSInput.glsl\";\r\n#include \"LayaPBRBRDF.glsl\";\r\n#include \"GlobalIllumination.glsl\";\r\n#include \"PBRCore.glsl\";\r\n\r\nvoid main()\r\n{\r\n\tfragmentForward();\r\n}";
|
||
|
||
var PBRVS$1 = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n\tprecision highp int;\r\n#else\r\n\tprecision mediump float;\r\n\tprecision mediump int;\r\n#endif\r\n#include \"Lighting.glsl\";\r\n#include \"LayaUtile.glsl\"\r\n#include \"Shadow.glsl\"\r\n#include \"PBRVSInput.glsl\";\r\n#include \"PBRVertex.glsl\";\r\n\r\nvoid main()\r\n{\r\n\tvertexForward();\r\n\tgl_Position=remapGLPositionZ(gl_Position);\r\n}";
|
||
|
||
var PBRShadowCasterPS$1 = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n\tprecision highp int;\r\n#else\r\n\tprecision mediump float;\r\n\tprecision mediump int;\r\n#endif\r\n\r\n#include \"ShadowCasterFS.glsl\"\r\n\r\nvoid main()\r\n{\r\n\tgl_FragColor=shadowCasterFragment();\r\n}";
|
||
|
||
var PBRShadowCasterVS$1 = "#include \"ShadowCasterVS.glsl\"\r\n\r\nvoid main()\r\n{\r\n\tvec4 positionCS = shadowCasterVertex();\r\n\tgl_Position=remapGLPositionZ(positionCS);\r\n}";
|
||
|
||
(function (PBRMetallicSmoothnessSource) {
|
||
PBRMetallicSmoothnessSource[PBRMetallicSmoothnessSource["MetallicGlossTextureAlpha"] = 0] = "MetallicGlossTextureAlpha";
|
||
PBRMetallicSmoothnessSource[PBRMetallicSmoothnessSource["AlbedoTextureAlpha"] = 1] = "AlbedoTextureAlpha";
|
||
})(exports.PBRMetallicSmoothnessSource || (exports.PBRMetallicSmoothnessSource = {}));
|
||
class PBRStandardMaterial extends PBRMaterial {
|
||
constructor() {
|
||
super();
|
||
this._smoothnessSource = 0;
|
||
this.setShaderName("PBR");
|
||
this._shaderValues.setNumber(PBRStandardMaterial.METALLIC, 0.0);
|
||
}
|
||
static __init__() {
|
||
PBRStandardMaterial.SHADERDEFINE_METALLICGLOSSTEXTURE = Shader3D.getDefineByName("METALLICGLOSSTEXTURE");
|
||
PBRStandardMaterial.SHADERDEFINE_SMOOTHNESSSOURCE_ALBEDOTEXTURE_ALPHA = Shader3D.getDefineByName("SMOOTHNESSSOURCE_ALBEDOTEXTURE_ALPHA");
|
||
var attributeMap = {
|
||
'a_Position': VertexMesh.MESH_POSITION0,
|
||
'a_Normal': VertexMesh.MESH_NORMAL0,
|
||
'a_Tangent0': VertexMesh.MESH_TANGENT0,
|
||
'a_Texcoord0': VertexMesh.MESH_TEXTURECOORDINATE0,
|
||
'a_Texcoord1': VertexMesh.MESH_TEXTURECOORDINATE1,
|
||
'a_BoneWeights': VertexMesh.MESH_BLENDWEIGHT0,
|
||
'a_BoneIndices': VertexMesh.MESH_BLENDINDICES0,
|
||
'a_WorldMat': VertexMesh.MESH_WORLDMATRIX_ROW0,
|
||
'a_SimpleTextureParams': VertexMesh.MESH_SIMPLEANIMATOR
|
||
};
|
||
var uniformMap = {
|
||
'u_Bones': Shader3D.PERIOD_CUSTOM,
|
||
'u_MvpMatrix': Shader3D.PERIOD_SPRITE,
|
||
'u_WorldMat': Shader3D.PERIOD_SPRITE,
|
||
'u_LightmapScaleOffset': Shader3D.PERIOD_SPRITE,
|
||
'u_LightMap': Shader3D.PERIOD_SPRITE,
|
||
'u_LightMapDirection': Shader3D.PERIOD_SPRITE,
|
||
'u_SimpleAnimatorTexture': Shader3D.PERIOD_SPRITE,
|
||
'u_SimpleAnimatorParams': Shader3D.PERIOD_SPRITE,
|
||
'u_SimpleAnimatorTextureSize': Shader3D.PERIOD_SPRITE,
|
||
'u_ReflectCubeHDRParams': Shader3D.PERIOD_SPRITE,
|
||
'u_ReflectTexture': Shader3D.PERIOD_SPRITE,
|
||
'u_SpecCubeProbePosition': Shader3D.PERIOD_SPRITE,
|
||
'u_SpecCubeBoxMax': Shader3D.PERIOD_SPRITE,
|
||
'u_SpecCubeBoxMin': Shader3D.PERIOD_SPRITE,
|
||
'u_CameraPos': Shader3D.PERIOD_CAMERA,
|
||
'u_View': Shader3D.PERIOD_CAMERA,
|
||
'u_ProjectionParams': Shader3D.PERIOD_CAMERA,
|
||
'u_Viewport': Shader3D.PERIOD_CAMERA,
|
||
'u_ViewProjection': Shader3D.PERIOD_CAMERA,
|
||
'u_AlphaTestValue': Shader3D.PERIOD_MATERIAL,
|
||
'u_AlbedoColor': Shader3D.PERIOD_MATERIAL,
|
||
'u_EmissionColor': Shader3D.PERIOD_MATERIAL,
|
||
'u_AlbedoTexture': Shader3D.PERIOD_MATERIAL,
|
||
'u_NormalTexture': Shader3D.PERIOD_MATERIAL,
|
||
'u_ParallaxTexture': Shader3D.PERIOD_MATERIAL,
|
||
'u_OcclusionTexture': Shader3D.PERIOD_MATERIAL,
|
||
'u_EmissionTexture': Shader3D.PERIOD_MATERIAL,
|
||
'u_Smoothness': Shader3D.PERIOD_MATERIAL,
|
||
'u_SmoothnessScale': Shader3D.PERIOD_MATERIAL,
|
||
'u_occlusionStrength': Shader3D.PERIOD_MATERIAL,
|
||
'u_NormalScale': Shader3D.PERIOD_MATERIAL,
|
||
'u_ParallaxScale': Shader3D.PERIOD_MATERIAL,
|
||
'u_TilingOffset': Shader3D.PERIOD_MATERIAL,
|
||
'u_MetallicGlossTexture': Shader3D.PERIOD_MATERIAL,
|
||
'u_Metallic': Shader3D.PERIOD_MATERIAL,
|
||
'u_AmbientColor': Shader3D.PERIOD_SCENE,
|
||
'u_FogStart': Shader3D.PERIOD_SCENE,
|
||
'u_FogRange': Shader3D.PERIOD_SCENE,
|
||
'u_FogColor': Shader3D.PERIOD_SCENE,
|
||
'u_DirationLightCount': Shader3D.PERIOD_SCENE,
|
||
'u_LightBuffer': Shader3D.PERIOD_SCENE,
|
||
'u_LightClusterBuffer': Shader3D.PERIOD_SCENE,
|
||
'u_ShadowBias': Shader3D.PERIOD_SCENE,
|
||
'u_ShadowLightDirection': Shader3D.PERIOD_SCENE,
|
||
'u_ShadowMap': Shader3D.PERIOD_SCENE,
|
||
'u_ShadowParams': Shader3D.PERIOD_SCENE,
|
||
'u_ShadowSplitSpheres': Shader3D.PERIOD_SCENE,
|
||
'u_ShadowMatrices': Shader3D.PERIOD_SCENE,
|
||
'u_ShadowMapSize': Shader3D.PERIOD_SCENE,
|
||
'u_SpotShadowMap': Shader3D.PERIOD_SCENE,
|
||
'u_SpotViewProjectMatrix': Shader3D.PERIOD_SCENE,
|
||
'u_ShadowLightPosition': Shader3D.PERIOD_SCENE,
|
||
'u_AmbientSHAr': Shader3D.PERIOD_SCENE,
|
||
'u_AmbientSHAg': Shader3D.PERIOD_SCENE,
|
||
'u_AmbientSHAb': Shader3D.PERIOD_SCENE,
|
||
'u_AmbientSHBr': Shader3D.PERIOD_SCENE,
|
||
'u_AmbientSHBg': Shader3D.PERIOD_SCENE,
|
||
'u_AmbientSHBb': Shader3D.PERIOD_SCENE,
|
||
'u_AmbientSHC': Shader3D.PERIOD_SCENE,
|
||
'u_DirectionLight.direction': Shader3D.PERIOD_SCENE,
|
||
'u_DirectionLight.color': Shader3D.PERIOD_SCENE,
|
||
'u_PointLight.position': Shader3D.PERIOD_SCENE,
|
||
'u_PointLight.range': Shader3D.PERIOD_SCENE,
|
||
'u_PointLight.color': Shader3D.PERIOD_SCENE,
|
||
'u_SpotLight.position': Shader3D.PERIOD_SCENE,
|
||
'u_SpotLight.direction': Shader3D.PERIOD_SCENE,
|
||
'u_SpotLight.range': Shader3D.PERIOD_SCENE,
|
||
'u_SpotLight.spot': Shader3D.PERIOD_SCENE,
|
||
'u_SpotLight.color': Shader3D.PERIOD_SCENE
|
||
};
|
||
var stateMap = {
|
||
's_Cull': Shader3D.RENDER_STATE_CULL,
|
||
's_Blend': Shader3D.RENDER_STATE_BLEND,
|
||
's_BlendSrc': Shader3D.RENDER_STATE_BLEND_SRC,
|
||
's_BlendDst': Shader3D.RENDER_STATE_BLEND_DST,
|
||
's_DepthTest': Shader3D.RENDER_STATE_DEPTH_TEST,
|
||
's_DepthWrite': Shader3D.RENDER_STATE_DEPTH_WRITE
|
||
};
|
||
var shader = Shader3D.add("PBR", attributeMap, uniformMap, true, true);
|
||
var subShader = new SubShader(attributeMap, uniformMap);
|
||
shader.addSubShader(subShader);
|
||
subShader.addShaderPass(PBRVS$1, PBRPS$1, stateMap, "Forward");
|
||
subShader.addShaderPass(PBRShadowCasterVS$1, PBRShadowCasterPS$1, stateMap, "ShadowCaster");
|
||
subShader.addShaderPass(DepthNormalsTextureVS, DepthNormalsTextureFS, stateMap, "DepthNormal");
|
||
}
|
||
get metallicGlossTexture() {
|
||
return this._shaderValues.getTexture(PBRStandardMaterial.METALLICGLOSSTEXTURE);
|
||
}
|
||
set metallicGlossTexture(value) {
|
||
if (value)
|
||
this._shaderValues.addDefine(PBRStandardMaterial.SHADERDEFINE_METALLICGLOSSTEXTURE);
|
||
else
|
||
this._shaderValues.removeDefine(PBRStandardMaterial.SHADERDEFINE_METALLICGLOSSTEXTURE);
|
||
this._shaderValues.setTexture(PBRStandardMaterial.METALLICGLOSSTEXTURE, value);
|
||
}
|
||
get metallic() {
|
||
return this._shaderValues.getNumber(PBRStandardMaterial.METALLIC);
|
||
}
|
||
set metallic(value) {
|
||
this._shaderValues.setNumber(PBRStandardMaterial.METALLIC, Math.max(0.0, Math.min(1.0, value)));
|
||
}
|
||
get smoothnessSource() {
|
||
return this._smoothnessSource;
|
||
}
|
||
set smoothnessSource(value) {
|
||
if (value)
|
||
this._shaderValues.addDefine(PBRStandardMaterial.SHADERDEFINE_SMOOTHNESSSOURCE_ALBEDOTEXTURE_ALPHA);
|
||
else
|
||
this._shaderValues.removeDefine(PBRStandardMaterial.SHADERDEFINE_SMOOTHNESSSOURCE_ALBEDOTEXTURE_ALPHA);
|
||
this._smoothnessSource = value;
|
||
}
|
||
clone() {
|
||
var dest = new PBRStandardMaterial();
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
}
|
||
PBRStandardMaterial.METALLICGLOSSTEXTURE = Shader3D.propertyNameToID("u_MetallicGlossTexture");
|
||
PBRStandardMaterial.METALLIC = Shader3D.propertyNameToID("u_Metallic");
|
||
|
||
class SkyBoxMaterial extends Material {
|
||
constructor() {
|
||
super();
|
||
this.setShaderName("SkyBox");
|
||
this.tintColor = new Vector4(0.5, 0.5, 0.5, 0.5);
|
||
this.exposure = 1.0;
|
||
this.rotation = 0;
|
||
}
|
||
static __initDefine__() {
|
||
}
|
||
get tintColor() {
|
||
return this._shaderValues.getVector(SkyBoxMaterial.TINTCOLOR);
|
||
}
|
||
set tintColor(value) {
|
||
this._shaderValues.setVector(SkyBoxMaterial.TINTCOLOR, value);
|
||
}
|
||
get exposure() {
|
||
return this._shaderValues.getNumber(SkyBoxMaterial.EXPOSURE);
|
||
}
|
||
set exposure(value) {
|
||
this._shaderValues.setNumber(SkyBoxMaterial.EXPOSURE, value);
|
||
}
|
||
get rotation() {
|
||
return this._shaderValues.getNumber(SkyBoxMaterial.ROTATION);
|
||
}
|
||
set rotation(value) {
|
||
this._shaderValues.setNumber(SkyBoxMaterial.ROTATION, value);
|
||
}
|
||
get textureCube() {
|
||
return this._shaderValues.getTexture(SkyBoxMaterial.TEXTURECUBE);
|
||
}
|
||
set textureCube(value) {
|
||
this._shaderValues.setTexture(SkyBoxMaterial.TEXTURECUBE, value);
|
||
}
|
||
clone() {
|
||
var dest = new SkyBoxMaterial();
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
}
|
||
SkyBoxMaterial.TINTCOLOR = Shader3D.propertyNameToID("u_TintColor");
|
||
SkyBoxMaterial.EXPOSURE = Shader3D.propertyNameToID("u_Exposure");
|
||
SkyBoxMaterial.ROTATION = Shader3D.propertyNameToID("u_Rotation");
|
||
SkyBoxMaterial.TEXTURECUBE = Shader3D.propertyNameToID("u_CubeTexture");
|
||
|
||
class SkyProceduralMaterial extends Material {
|
||
constructor() {
|
||
super();
|
||
this.setShaderName("SkyBoxProcedural");
|
||
this.sunDisk = SkyProceduralMaterial.SUN_HIGH_QUALITY;
|
||
this.sunSize = 0.04;
|
||
this.sunSizeConvergence = 5;
|
||
this.atmosphereThickness = 1.0;
|
||
this.skyTint = new Vector4(0.5, 0.5, 0.5, 1.0);
|
||
this.groundTint = new Vector4(0.369, 0.349, 0.341, 1.0);
|
||
this.exposure = 1.3;
|
||
}
|
||
static __initDefine__() {
|
||
SkyProceduralMaterial.SHADERDEFINE_SUN_HIGH_QUALITY = Shader3D.getDefineByName("SUN_HIGH_QUALITY");
|
||
SkyProceduralMaterial.SHADERDEFINE_SUN_SIMPLE = Shader3D.getDefineByName("SUN_SIMPLE");
|
||
}
|
||
get sunDisk() {
|
||
return this._sunDisk;
|
||
}
|
||
set sunDisk(value) {
|
||
switch (value) {
|
||
case SkyProceduralMaterial.SUN_HIGH_QUALITY:
|
||
this._shaderValues.removeDefine(SkyProceduralMaterial.SHADERDEFINE_SUN_SIMPLE);
|
||
this._shaderValues.addDefine(SkyProceduralMaterial.SHADERDEFINE_SUN_HIGH_QUALITY);
|
||
break;
|
||
case SkyProceduralMaterial.SUN_SIMPLE:
|
||
this._shaderValues.removeDefine(SkyProceduralMaterial.SHADERDEFINE_SUN_HIGH_QUALITY);
|
||
this._shaderValues.addDefine(SkyProceduralMaterial.SHADERDEFINE_SUN_SIMPLE);
|
||
break;
|
||
case SkyProceduralMaterial.SUN_NODE:
|
||
this._shaderValues.removeDefine(SkyProceduralMaterial.SHADERDEFINE_SUN_HIGH_QUALITY);
|
||
this._shaderValues.removeDefine(SkyProceduralMaterial.SHADERDEFINE_SUN_SIMPLE);
|
||
break;
|
||
default:
|
||
throw "SkyBoxProceduralMaterial: unknown sun value.";
|
||
}
|
||
this._sunDisk = value;
|
||
}
|
||
get sunSize() {
|
||
return this._shaderValues.getNumber(SkyProceduralMaterial.SUNSIZE);
|
||
}
|
||
set sunSize(value) {
|
||
value = Math.min(Math.max(0.0, value), 1.0);
|
||
this._shaderValues.setNumber(SkyProceduralMaterial.SUNSIZE, value);
|
||
}
|
||
get sunSizeConvergence() {
|
||
return this._shaderValues.getNumber(SkyProceduralMaterial.SUNSIZECONVERGENCE);
|
||
}
|
||
set sunSizeConvergence(value) {
|
||
value = Math.min(Math.max(0.0, value), 20.0);
|
||
this._shaderValues.setNumber(SkyProceduralMaterial.SUNSIZECONVERGENCE, value);
|
||
}
|
||
get atmosphereThickness() {
|
||
return this._shaderValues.getNumber(SkyProceduralMaterial.ATMOSPHERETHICKNESS);
|
||
}
|
||
set atmosphereThickness(value) {
|
||
value = Math.min(Math.max(0.0, value), 5.0);
|
||
this._shaderValues.setNumber(SkyProceduralMaterial.ATMOSPHERETHICKNESS, value);
|
||
}
|
||
get skyTint() {
|
||
return this._shaderValues.getVector(SkyProceduralMaterial.SKYTINT);
|
||
}
|
||
set skyTint(value) {
|
||
this._shaderValues.setVector(SkyProceduralMaterial.SKYTINT, value);
|
||
}
|
||
get groundTint() {
|
||
return this._shaderValues.getVector(SkyProceduralMaterial.GROUNDTINT);
|
||
}
|
||
set groundTint(value) {
|
||
this._shaderValues.setVector(SkyProceduralMaterial.GROUNDTINT, value);
|
||
}
|
||
get exposure() {
|
||
return this._shaderValues.getNumber(SkyProceduralMaterial.EXPOSURE);
|
||
}
|
||
set exposure(value) {
|
||
value = Math.min(Math.max(0.0, value), 8.0);
|
||
this._shaderValues.setNumber(SkyProceduralMaterial.EXPOSURE, value);
|
||
}
|
||
clone() {
|
||
var dest = new SkyProceduralMaterial();
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
}
|
||
SkyProceduralMaterial.SUN_NODE = 0;
|
||
SkyProceduralMaterial.SUN_SIMPLE = 1;
|
||
SkyProceduralMaterial.SUN_HIGH_QUALITY = 2;
|
||
SkyProceduralMaterial.SUNSIZE = Shader3D.propertyNameToID("u_SunSize");
|
||
SkyProceduralMaterial.SUNSIZECONVERGENCE = Shader3D.propertyNameToID("u_SunSizeConvergence");
|
||
SkyProceduralMaterial.ATMOSPHERETHICKNESS = Shader3D.propertyNameToID("u_AtmosphereThickness");
|
||
SkyProceduralMaterial.SKYTINT = Shader3D.propertyNameToID("u_SkyTint");
|
||
SkyProceduralMaterial.GROUNDTINT = Shader3D.propertyNameToID("u_GroundTint");
|
||
SkyProceduralMaterial.EXPOSURE = Shader3D.propertyNameToID("u_Exposure");
|
||
|
||
class UnlitMaterial extends Material {
|
||
constructor() {
|
||
super();
|
||
this.setShaderName("Unlit");
|
||
this._shaderValues.setVector(UnlitMaterial.ALBEDOCOLOR, new Vector4(1.0, 1.0, 1.0, 1.0));
|
||
this._shaderValues.setVector(UnlitMaterial.TILINGOFFSET, new Vector4(1.0, 1.0, 0.0, 0.0));
|
||
this.renderMode = UnlitMaterial.RENDERMODE_OPAQUE;
|
||
this.albedoIntensity = 1.0;
|
||
}
|
||
static __initDefine__() {
|
||
UnlitMaterial.SHADERDEFINE_ALBEDOTEXTURE = Shader3D.getDefineByName("ALBEDOTEXTURE");
|
||
UnlitMaterial.SHADERDEFINE_ENABLEVERTEXCOLOR = Shader3D.getDefineByName("ENABLEVERTEXCOLOR");
|
||
}
|
||
get _ColorR() {
|
||
return this.albedoColor.x;
|
||
}
|
||
set _ColorR(value) {
|
||
let albedo = this.albedoColor;
|
||
albedo.x = value;
|
||
this.albedoColor = albedo;
|
||
}
|
||
get _ColorG() {
|
||
return this.albedoColor.y;
|
||
}
|
||
set _ColorG(value) {
|
||
let albedo = this.albedoColor;
|
||
albedo.y = value;
|
||
this.albedoColor = albedo;
|
||
}
|
||
get _ColorB() {
|
||
return this.albedoColor.z;
|
||
}
|
||
set _ColorB(value) {
|
||
let albedo = this.albedoColor;
|
||
albedo.z = value;
|
||
this.albedoColor = albedo;
|
||
}
|
||
get _ColorA() {
|
||
return this.albedoColor.w;
|
||
}
|
||
set _ColorA(value) {
|
||
let albedo = this.albedoColor;
|
||
albedo.w = value;
|
||
this.albedoColor = albedo;
|
||
}
|
||
get _Color() {
|
||
return this._shaderValues.getVector(UnlitMaterial.ALBEDOCOLOR);
|
||
}
|
||
set _Color(value) {
|
||
this.albedoColor = value;
|
||
}
|
||
get _AlbedoIntensity() {
|
||
return this._albedoIntensity;
|
||
}
|
||
set _AlbedoIntensity(value) {
|
||
if (this._albedoIntensity !== value) {
|
||
var finalAlbedo = this._shaderValues.getVector(UnlitMaterial.ALBEDOCOLOR);
|
||
Vector4.scale(this.albedoColor, value, finalAlbedo);
|
||
this._albedoIntensity = value;
|
||
this._shaderValues.setVector(UnlitMaterial.ALBEDOCOLOR, finalAlbedo);
|
||
}
|
||
}
|
||
get _MainTex_STX() {
|
||
return this._shaderValues.getVector(UnlitMaterial.TILINGOFFSET).x;
|
||
}
|
||
set _MainTex_STX(x) {
|
||
var tilOff = this._shaderValues.getVector(UnlitMaterial.TILINGOFFSET);
|
||
tilOff.x = x;
|
||
this.tilingOffset = tilOff;
|
||
}
|
||
get _MainTex_STY() {
|
||
return this._shaderValues.getVector(UnlitMaterial.TILINGOFFSET).y;
|
||
}
|
||
set _MainTex_STY(y) {
|
||
var tilOff = this._shaderValues.getVector(UnlitMaterial.TILINGOFFSET);
|
||
tilOff.y = y;
|
||
this.tilingOffset = tilOff;
|
||
}
|
||
get _MainTex_STZ() {
|
||
return this._shaderValues.getVector(UnlitMaterial.TILINGOFFSET).z;
|
||
}
|
||
set _MainTex_STZ(z) {
|
||
var tilOff = this._shaderValues.getVector(UnlitMaterial.TILINGOFFSET);
|
||
tilOff.z = z;
|
||
this.tilingOffset = tilOff;
|
||
}
|
||
get _MainTex_STW() {
|
||
return this._shaderValues.getVector(UnlitMaterial.TILINGOFFSET).w;
|
||
}
|
||
set _MainTex_STW(w) {
|
||
var tilOff = this._shaderValues.getVector(UnlitMaterial.TILINGOFFSET);
|
||
tilOff.w = w;
|
||
this.tilingOffset = tilOff;
|
||
}
|
||
get _MainTex_ST() {
|
||
return this._shaderValues.getVector(UnlitMaterial.TILINGOFFSET);
|
||
}
|
||
set _MainTex_ST(value) {
|
||
this.tilingOffset = value;
|
||
}
|
||
get _Cutoff() {
|
||
return this.alphaTestValue;
|
||
}
|
||
set _Cutoff(value) {
|
||
this.alphaTestValue = value;
|
||
}
|
||
get albedoColorR() {
|
||
return this._ColorR;
|
||
}
|
||
set albedoColorR(value) {
|
||
this._ColorR = value;
|
||
}
|
||
get albedoColorG() {
|
||
return this._ColorG;
|
||
}
|
||
set albedoColorG(value) {
|
||
this._ColorG = value;
|
||
}
|
||
get albedoColorB() {
|
||
return this._ColorB;
|
||
}
|
||
set albedoColorB(value) {
|
||
this._ColorB = value;
|
||
}
|
||
get albedoColorA() {
|
||
return this._ColorA;
|
||
}
|
||
set albedoColorA(value) {
|
||
this._ColorA = value;
|
||
}
|
||
get albedoColor() {
|
||
return this._shaderValues.getVector(UnlitMaterial.ALBEDOCOLOR);
|
||
}
|
||
set albedoColor(value) {
|
||
var finalAlbedo = this._shaderValues.getVector(UnlitMaterial.ALBEDOCOLOR);
|
||
Vector4.scale(value, this._albedoIntensity, finalAlbedo);
|
||
this._shaderValues.setVector(UnlitMaterial.ALBEDOCOLOR, finalAlbedo);
|
||
}
|
||
get albedoIntensity() {
|
||
return this._albedoIntensity;
|
||
}
|
||
set albedoIntensity(value) {
|
||
this._AlbedoIntensity = value;
|
||
}
|
||
get albedoTexture() {
|
||
return this._shaderValues.getTexture(UnlitMaterial.ALBEDOTEXTURE);
|
||
}
|
||
set albedoTexture(value) {
|
||
if (value)
|
||
this._shaderValues.addDefine(UnlitMaterial.SHADERDEFINE_ALBEDOTEXTURE);
|
||
else
|
||
this._shaderValues.removeDefine(UnlitMaterial.SHADERDEFINE_ALBEDOTEXTURE);
|
||
this._shaderValues.setTexture(UnlitMaterial.ALBEDOTEXTURE, value);
|
||
}
|
||
get tilingOffsetX() {
|
||
return this._MainTex_STX;
|
||
}
|
||
set tilingOffsetX(x) {
|
||
this._MainTex_STX = x;
|
||
}
|
||
get tilingOffsetY() {
|
||
return this._MainTex_STY;
|
||
}
|
||
set tilingOffsetY(y) {
|
||
this._MainTex_STY = y;
|
||
}
|
||
get tilingOffsetZ() {
|
||
return this._MainTex_STZ;
|
||
}
|
||
set tilingOffsetZ(z) {
|
||
this._MainTex_STZ = z;
|
||
}
|
||
get tilingOffsetW() {
|
||
return this._MainTex_STW;
|
||
}
|
||
set tilingOffsetW(w) {
|
||
this._MainTex_STW = w;
|
||
}
|
||
get tilingOffset() {
|
||
return this._shaderValues.getVector(UnlitMaterial.TILINGOFFSET);
|
||
}
|
||
set tilingOffset(value) {
|
||
if (value) {
|
||
this._shaderValues.setVector(UnlitMaterial.TILINGOFFSET, value);
|
||
}
|
||
else {
|
||
this._shaderValues.getVector(UnlitMaterial.TILINGOFFSET).setValue(1.0, 1.0, 0.0, 0.0);
|
||
}
|
||
}
|
||
get enableVertexColor() {
|
||
return this._shaderValues.hasDefine(UnlitMaterial.SHADERDEFINE_ENABLEVERTEXCOLOR);
|
||
}
|
||
set enableVertexColor(value) {
|
||
if (value)
|
||
this._shaderValues.addDefine(UnlitMaterial.SHADERDEFINE_ENABLEVERTEXCOLOR);
|
||
else
|
||
this._shaderValues.removeDefine(UnlitMaterial.SHADERDEFINE_ENABLEVERTEXCOLOR);
|
||
}
|
||
set renderMode(value) {
|
||
switch (value) {
|
||
case UnlitMaterial.RENDERMODE_OPAQUE:
|
||
this.alphaTest = false;
|
||
this.renderQueue = Material.RENDERQUEUE_OPAQUE;
|
||
this.depthWrite = true;
|
||
this.cull = RenderState.CULL_BACK;
|
||
this.blend = RenderState.BLEND_DISABLE;
|
||
this.depthTest = RenderState.DEPTHTEST_LESS;
|
||
break;
|
||
case UnlitMaterial.RENDERMODE_CUTOUT:
|
||
this.renderQueue = Material.RENDERQUEUE_ALPHATEST;
|
||
this.alphaTest = true;
|
||
this.depthWrite = true;
|
||
this.cull = RenderState.CULL_BACK;
|
||
this.blend = RenderState.BLEND_DISABLE;
|
||
this.depthTest = RenderState.DEPTHTEST_LESS;
|
||
break;
|
||
case UnlitMaterial.RENDERMODE_TRANSPARENT:
|
||
this.renderQueue = Material.RENDERQUEUE_TRANSPARENT;
|
||
this.alphaTest = false;
|
||
this.depthWrite = false;
|
||
this.cull = RenderState.CULL_BACK;
|
||
this.blend = RenderState.BLEND_ENABLE_ALL;
|
||
this.blendSrc = RenderState.BLENDPARAM_SRC_ALPHA;
|
||
this.blendDst = RenderState.BLENDPARAM_ONE_MINUS_SRC_ALPHA;
|
||
this.depthTest = RenderState.DEPTHTEST_LESS;
|
||
break;
|
||
default:
|
||
throw new Error("UnlitMaterial : renderMode value error.");
|
||
}
|
||
}
|
||
clone() {
|
||
var dest = new UnlitMaterial();
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
}
|
||
UnlitMaterial.RENDERMODE_OPAQUE = 0;
|
||
UnlitMaterial.RENDERMODE_CUTOUT = 1;
|
||
UnlitMaterial.RENDERMODE_TRANSPARENT = 2;
|
||
UnlitMaterial.RENDERMODE_ADDTIVE = 3;
|
||
UnlitMaterial.ALBEDOTEXTURE = Shader3D.propertyNameToID("u_AlbedoTexture");
|
||
UnlitMaterial.ALBEDOCOLOR = Shader3D.propertyNameToID("u_AlbedoColor");
|
||
UnlitMaterial.TILINGOFFSET = Shader3D.propertyNameToID("u_TilingOffset");
|
||
|
||
class WaterPrimaryMaterial extends Material {
|
||
constructor() {
|
||
super();
|
||
this.setShaderName("WaterPrimary");
|
||
this._shaderValues.setVector(WaterPrimaryMaterial.HORIZONCOLOR, new Vector4(0.172, 0.463, 0.435, 0));
|
||
this._shaderValues.setNumber(WaterPrimaryMaterial.WAVESCALE, 0.15);
|
||
this._shaderValues.setVector(WaterPrimaryMaterial.WAVESPEED, new Vector4(19, 9, -16, -7));
|
||
}
|
||
static __initDefine__() {
|
||
WaterPrimaryMaterial.SHADERDEFINE_MAINTEXTURE = Shader3D.getDefineByName("MAINTEXTURE");
|
||
WaterPrimaryMaterial.SHADERDEFINE_NORMALTEXTURE = Shader3D.getDefineByName("NORMALTEXTURE");
|
||
}
|
||
get horizonColor() {
|
||
return this._shaderValues.getVector(WaterPrimaryMaterial.HORIZONCOLOR);
|
||
}
|
||
set horizonColor(value) {
|
||
this._shaderValues.setVector(WaterPrimaryMaterial.HORIZONCOLOR, value);
|
||
}
|
||
get mainTexture() {
|
||
return this._shaderValues.getTexture(WaterPrimaryMaterial.MAINTEXTURE);
|
||
}
|
||
set mainTexture(value) {
|
||
if (value)
|
||
this._shaderValues.addDefine(WaterPrimaryMaterial.SHADERDEFINE_MAINTEXTURE);
|
||
else
|
||
this._shaderValues.removeDefine(WaterPrimaryMaterial.SHADERDEFINE_MAINTEXTURE);
|
||
this._shaderValues.setTexture(WaterPrimaryMaterial.MAINTEXTURE, value);
|
||
}
|
||
get normalTexture() {
|
||
return this._shaderValues.getTexture(WaterPrimaryMaterial.NORMALTEXTURE);
|
||
}
|
||
set normalTexture(value) {
|
||
if (value)
|
||
this._shaderValues.addDefine(WaterPrimaryMaterial.SHADERDEFINE_NORMALTEXTURE);
|
||
else
|
||
this._shaderValues.removeDefine(WaterPrimaryMaterial.SHADERDEFINE_NORMALTEXTURE);
|
||
this._shaderValues.setTexture(WaterPrimaryMaterial.NORMALTEXTURE, value);
|
||
}
|
||
get waveScale() {
|
||
return this._shaderValues.getNumber(WaterPrimaryMaterial.WAVESCALE);
|
||
}
|
||
set waveScale(value) {
|
||
this._shaderValues.setNumber(WaterPrimaryMaterial.WAVESCALE, value);
|
||
}
|
||
get waveSpeed() {
|
||
return this._shaderValues.getVector(WaterPrimaryMaterial.WAVESPEED);
|
||
}
|
||
set waveSpeed(value) {
|
||
this._shaderValues.setVector(WaterPrimaryMaterial.WAVESPEED, value);
|
||
}
|
||
clone() {
|
||
var dest = new WaterPrimaryMaterial();
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
}
|
||
WaterPrimaryMaterial.HORIZONCOLOR = Shader3D.propertyNameToID("u_HorizonColor");
|
||
WaterPrimaryMaterial.MAINTEXTURE = Shader3D.propertyNameToID("u_MainTexture");
|
||
WaterPrimaryMaterial.NORMALTEXTURE = Shader3D.propertyNameToID("u_NormalTexture");
|
||
WaterPrimaryMaterial.WAVESCALE = Shader3D.propertyNameToID("u_WaveScale");
|
||
WaterPrimaryMaterial.WAVESPEED = Shader3D.propertyNameToID("u_WaveSpeed");
|
||
|
||
class MeshRenderer extends BaseRender {
|
||
constructor(owner) {
|
||
super(owner);
|
||
this._revertStaticBatchDefineUV1 = false;
|
||
this._projectionViewWorldMatrix = new Matrix4x4();
|
||
}
|
||
_createRenderElement() {
|
||
return new SubMeshRenderElement();
|
||
}
|
||
_onMeshChange(mesh) {
|
||
if (mesh) {
|
||
var count = mesh.subMeshCount;
|
||
this._renderElements.length = count;
|
||
for (var i = 0; i < count; i++) {
|
||
var renderElement = this._renderElements[i];
|
||
if (!renderElement) {
|
||
var material = this.sharedMaterials[i];
|
||
renderElement = this._renderElements[i] = this._createRenderElement();
|
||
renderElement.setTransform(this._owner._transform);
|
||
renderElement.render = this;
|
||
renderElement.material = material ? material : BlinnPhongMaterial.defaultMaterial;
|
||
}
|
||
renderElement.setGeometry(mesh.getSubMesh(i));
|
||
}
|
||
}
|
||
else {
|
||
this._renderElements.length = 0;
|
||
}
|
||
this._boundsChange = true;
|
||
}
|
||
_calculateBoundingBox() {
|
||
var sharedMesh = this._owner.meshFilter.sharedMesh;
|
||
if (sharedMesh) {
|
||
var worldMat = this._owner.transform.worldMatrix;
|
||
sharedMesh.bounds._tranform(worldMat, this._bounds);
|
||
}
|
||
}
|
||
_needRender(boundFrustum, context) {
|
||
if (boundFrustum)
|
||
return boundFrustum.intersects(this.bounds._getBoundBox());
|
||
else
|
||
return true;
|
||
}
|
||
_renderUpdate(context, transform) {
|
||
this._applyLightMapParams();
|
||
var element = context.renderElement;
|
||
switch (element.renderType) {
|
||
case RenderElement.RENDERTYPE_NORMAL:
|
||
this._shaderValues.setMatrix4x4(Sprite3D.WORLDMATRIX, transform.worldMatrix);
|
||
break;
|
||
case RenderElement.RENDERTYPE_STATICBATCH:
|
||
if (transform)
|
||
this._shaderValues.setMatrix4x4(Sprite3D.WORLDMATRIX, transform.worldMatrix);
|
||
else
|
||
this._shaderValues.setMatrix4x4(Sprite3D.WORLDMATRIX, Matrix4x4.DEFAULT);
|
||
if (!this._shaderValues.hasDefine(MeshSprite3DShaderDeclaration.SHADERDEFINE_UV1)) {
|
||
this._shaderValues.addDefine(MeshSprite3DShaderDeclaration.SHADERDEFINE_UV1);
|
||
this._revertStaticBatchDefineUV1 = true;
|
||
}
|
||
else {
|
||
this._revertStaticBatchDefineUV1 = false;
|
||
}
|
||
this._shaderValues.setVector(RenderableSprite3D.LIGHTMAPSCALEOFFSET, BaseRender._defaultLightmapScaleOffset);
|
||
break;
|
||
case RenderElement.RENDERTYPE_VERTEXBATCH:
|
||
this._shaderValues.setMatrix4x4(Sprite3D.WORLDMATRIX, Matrix4x4.DEFAULT);
|
||
break;
|
||
case RenderElement.RENDERTYPE_INSTANCEBATCH:
|
||
var worldMatrixData = SubMeshInstanceBatch.instance.instanceWorldMatrixData;
|
||
var insBatches = element.instanceBatchElementList;
|
||
var elements = insBatches.elements;
|
||
var count = insBatches.length;
|
||
for (var i = 0; i < count; i++)
|
||
worldMatrixData.set(elements[i]._transform.worldMatrix.elements, i * 16);
|
||
var worldBuffer = SubMeshInstanceBatch.instance.instanceWorldMatrixBuffer;
|
||
worldBuffer.orphanStorage();
|
||
worldBuffer.setData(worldMatrixData.buffer, 0, 0, count * 16 * 4);
|
||
this._shaderValues.addDefine(MeshSprite3DShaderDeclaration.SHADERDEFINE_GPU_INSTANCE);
|
||
break;
|
||
}
|
||
if (!this._probReflection)
|
||
return;
|
||
if (this._reflectionMode == exports.ReflectionProbeMode.off) {
|
||
this._shaderValues.removeDefine(MeshSprite3DShaderDeclaration.SHADERDEFINE_SPECCUBE_BOX_PROJECTION);
|
||
this._shaderValues.setVector(RenderableSprite3D.REFLECTIONCUBE_HDR_PARAMS, ReflectionProbe.defaultTextureHDRDecodeValues);
|
||
this._shaderValues.setTexture(RenderableSprite3D.REFLECTIONTEXTURE, TextureCube.blackTexture);
|
||
}
|
||
else {
|
||
if (!this._probReflection.boxProjection) {
|
||
this._shaderValues.removeDefine(MeshSprite3DShaderDeclaration.SHADERDEFINE_SPECCUBE_BOX_PROJECTION);
|
||
}
|
||
else {
|
||
this._shaderValues.addDefine(MeshSprite3DShaderDeclaration.SHADERDEFINE_SPECCUBE_BOX_PROJECTION);
|
||
this._shaderValues.setVector3(RenderableSprite3D.REFLECTIONCUBE_PROBEPOSITION, this._probReflection.probePosition);
|
||
this._shaderValues.setVector3(RenderableSprite3D.REFLECTIONCUBE_PROBEBOXMAX, this._probReflection.boundsMax);
|
||
this._shaderValues.setVector3(RenderableSprite3D.REFLECTIONCUBE_PROBEBOXMIN, this._probReflection.boundsMin);
|
||
}
|
||
this._shaderValues.setTexture(RenderableSprite3D.REFLECTIONTEXTURE, this._probReflection.reflectionTexture);
|
||
this._shaderValues.setVector(RenderableSprite3D.REFLECTIONCUBE_HDR_PARAMS, this._probReflection.reflectionHDRParams);
|
||
}
|
||
}
|
||
_renderUpdateWithCamera(context, transform) {
|
||
var projectionView = context.projectionViewMatrix;
|
||
if (projectionView) {
|
||
var element = context.renderElement;
|
||
switch (element.renderType) {
|
||
case RenderElement.RENDERTYPE_NORMAL:
|
||
case RenderElement.RENDERTYPE_STATICBATCH:
|
||
case RenderElement.RENDERTYPE_VERTEXBATCH:
|
||
if (transform) {
|
||
Matrix4x4.multiply(projectionView, transform.worldMatrix, this._projectionViewWorldMatrix);
|
||
this._shaderValues.setMatrix4x4(Sprite3D.MVPMATRIX, this._projectionViewWorldMatrix);
|
||
}
|
||
else {
|
||
this._shaderValues.setMatrix4x4(Sprite3D.MVPMATRIX, projectionView);
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
_revertBatchRenderUpdate(context) {
|
||
var element = context.renderElement;
|
||
switch (element.renderType) {
|
||
case RenderElement.RENDERTYPE_STATICBATCH:
|
||
if (this._revertStaticBatchDefineUV1)
|
||
this._shaderValues.removeDefine(MeshSprite3DShaderDeclaration.SHADERDEFINE_UV1);
|
||
this._shaderValues.setVector(RenderableSprite3D.LIGHTMAPSCALEOFFSET, this.lightmapScaleOffset);
|
||
break;
|
||
case RenderElement.RENDERTYPE_INSTANCEBATCH:
|
||
this._shaderValues.removeDefine(MeshSprite3DShaderDeclaration.SHADERDEFINE_GPU_INSTANCE);
|
||
break;
|
||
}
|
||
}
|
||
_destroy() {
|
||
(this._isPartOfStaticBatch) && (MeshRenderStaticBatchManager.instance._removeRenderSprite(this._owner));
|
||
super._destroy();
|
||
}
|
||
}
|
||
|
||
class MeshFilter {
|
||
constructor(owner) {
|
||
this._owner = owner;
|
||
}
|
||
get sharedMesh() {
|
||
return this._sharedMesh;
|
||
}
|
||
set sharedMesh(value) {
|
||
if (this._sharedMesh !== value) {
|
||
var defineDatas = this._owner._render._shaderValues;
|
||
var lastValue = this._sharedMesh;
|
||
if (lastValue) {
|
||
lastValue._removeReference();
|
||
this._getMeshDefine(lastValue, MeshFilter._meshVerticeDefine);
|
||
for (var i = 0, n = MeshFilter._meshVerticeDefine.length; i < n; i++)
|
||
defineDatas.removeDefine(MeshFilter._meshVerticeDefine[i]);
|
||
}
|
||
if (value) {
|
||
value._addReference();
|
||
this._getMeshDefine(value, MeshFilter._meshVerticeDefine);
|
||
for (var i = 0, n = MeshFilter._meshVerticeDefine.length; i < n; i++)
|
||
defineDatas.addDefine(MeshFilter._meshVerticeDefine[i]);
|
||
}
|
||
this._owner._render._onMeshChange(value);
|
||
this._sharedMesh = value;
|
||
}
|
||
}
|
||
_getMeshDefine(mesh, out) {
|
||
out.length = 0;
|
||
var define;
|
||
for (var i = 0, n = mesh._subMeshes.length; i < n; i++) {
|
||
var subMesh = mesh.getSubMesh(i);
|
||
var vertexElements = subMesh._vertexBuffer._vertexDeclaration._vertexElements;
|
||
for (var j = 0, m = vertexElements.length; j < m; j++) {
|
||
var vertexElement = vertexElements[j];
|
||
var name = vertexElement._elementUsage;
|
||
switch (name) {
|
||
case VertexMesh.MESH_COLOR0:
|
||
out.push(MeshSprite3DShaderDeclaration.SHADERDEFINE_COLOR);
|
||
break;
|
||
case VertexMesh.MESH_TEXTURECOORDINATE0:
|
||
out.push(MeshSprite3DShaderDeclaration.SHADERDEFINE_UV0);
|
||
break;
|
||
case VertexMesh.MESH_TEXTURECOORDINATE1:
|
||
out.push(MeshSprite3DShaderDeclaration.SHADERDEFINE_UV1);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
return define;
|
||
}
|
||
destroy() {
|
||
this._owner = null;
|
||
(this._sharedMesh) && (this._sharedMesh._removeReference(), this._sharedMesh = null);
|
||
}
|
||
}
|
||
MeshFilter._meshVerticeDefine = [];
|
||
|
||
class SubMeshDynamicBatch extends GeometryElement {
|
||
constructor() {
|
||
super();
|
||
this._bufferState = new BufferState();
|
||
var gl = Laya.LayaGL.instance;
|
||
var maxVerDec = VertexMesh.getVertexDeclaration("POSITION,NORMAL,COLOR,UV,UV1,TANGENT");
|
||
var maxByteCount = maxVerDec.vertexStride * SubMeshDynamicBatch.maxIndicesCount;
|
||
this._vertices = new Float32Array(maxByteCount / 4);
|
||
this._vertexBuffer = new VertexBuffer3D(maxByteCount, gl.DYNAMIC_DRAW);
|
||
this._indices = new Int16Array(SubMeshDynamicBatch.maxIndicesCount);
|
||
this._indexBuffer = new IndexBuffer3D(exports.IndexFormat.UInt16, this._indices.length, gl.DYNAMIC_DRAW);
|
||
var memorySize = this._vertexBuffer._byteLength + this._indexBuffer._byteLength;
|
||
Laya.Resource._addMemory(memorySize, memorySize);
|
||
}
|
||
static __init__() {
|
||
SubMeshDynamicBatch.instance = new SubMeshDynamicBatch();
|
||
}
|
||
_getBatchVertices(vertexDeclaration, batchVertices, batchOffset, element, subMesh) {
|
||
var vertexFloatCount = vertexDeclaration.vertexStride / 4;
|
||
var oriVertexes = subMesh._vertexBuffer.getFloat32Data();
|
||
var multiSubMesh = element._dynamicMultiSubMesh;
|
||
var vertexCount = element._dynamicVertexCount;
|
||
element._computeWorldPositionsAndNormals(this._positionOffset, this._normalOffset, multiSubMesh, vertexCount);
|
||
var worldPositions = element._dynamicWorldPositions;
|
||
var worldNormals = element._dynamicWorldNormals;
|
||
var indices = subMesh._indices;
|
||
for (var i = 0; i < vertexCount; i++) {
|
||
var index = multiSubMesh ? indices[i] : i;
|
||
var oriOffset = index * vertexFloatCount;
|
||
var bakeOffset = (i + batchOffset) * vertexFloatCount;
|
||
var oriOff = i * 3;
|
||
var bakOff = bakeOffset + this._positionOffset;
|
||
batchVertices[bakOff] = worldPositions[oriOff];
|
||
batchVertices[bakOff + 1] = worldPositions[oriOff + 1];
|
||
batchVertices[bakOff + 2] = worldPositions[oriOff + 2];
|
||
if (this._normalOffset !== -1) {
|
||
bakOff = bakeOffset + this._normalOffset;
|
||
batchVertices[bakOff] = worldNormals[oriOff];
|
||
batchVertices[bakOff + 1] = worldNormals[oriOff + 1];
|
||
batchVertices[bakOff + 2] = worldNormals[oriOff + 2];
|
||
}
|
||
if (this._colorOffset !== -1) {
|
||
bakOff = bakeOffset + this._colorOffset;
|
||
oriOff = oriOffset + this._colorOffset;
|
||
batchVertices[bakOff] = oriVertexes[oriOff];
|
||
batchVertices[bakOff + 1] = oriVertexes[oriOff + 1];
|
||
batchVertices[bakOff + 2] = oriVertexes[oriOff + 2];
|
||
batchVertices[bakOff + 3] = oriVertexes[oriOff + 3];
|
||
}
|
||
if (this._uv0Offset !== -1) {
|
||
bakOff = bakeOffset + this._uv0Offset;
|
||
oriOff = oriOffset + this._uv0Offset;
|
||
batchVertices[bakOff] = oriVertexes[oriOff];
|
||
batchVertices[bakOff + 1] = oriVertexes[oriOff + 1];
|
||
}
|
||
if (this._sTangentOffset !== -1) {
|
||
bakOff = bakeOffset + this._sTangentOffset;
|
||
oriOff = oriOffset + this._sTangentOffset;
|
||
batchVertices[bakOff] = oriVertexes[oriOff];
|
||
batchVertices[bakOff + 1] = oriVertexes[oriOff + 1];
|
||
batchVertices[bakOff + 2] = oriVertexes[oriOff + 2];
|
||
batchVertices[bakOff + 3] = oriVertexes[oriOff + 3];
|
||
bakOff = bakeOffset + this._sTangentOffset;
|
||
oriOff = oriOffset + this._sTangentOffset;
|
||
batchVertices[bakOff] = oriVertexes[oriOff];
|
||
batchVertices[bakOff + 1] = oriVertexes[oriOff + 1];
|
||
batchVertices[bakOff + 2] = oriVertexes[oriOff + 2];
|
||
batchVertices[bakOff + 3] = oriVertexes[oriOff + 3];
|
||
}
|
||
}
|
||
}
|
||
_getBatchIndices(batchIndices, batchIndexCount, batchVertexCount, transform, subMesh, multiSubMesh) {
|
||
var subIndices = subMesh._indices;
|
||
var k, m, batchOffset;
|
||
var isInvert = transform._isFrontFaceInvert;
|
||
if (multiSubMesh) {
|
||
if (isInvert) {
|
||
for (k = 0, m = subIndices.length; k < m; k += 3) {
|
||
batchOffset = batchIndexCount + k;
|
||
var index = batchVertexCount + k;
|
||
batchIndices[batchOffset] = index;
|
||
batchIndices[batchOffset + 1] = index + 2;
|
||
batchIndices[batchOffset + 2] = index + 1;
|
||
}
|
||
}
|
||
else {
|
||
for (k = 0, m = subIndices.length; k < m; k += 3) {
|
||
batchOffset = batchIndexCount + k;
|
||
index = batchVertexCount + k;
|
||
batchIndices[batchOffset] = index;
|
||
batchIndices[batchOffset + 1] = index + 1;
|
||
batchIndices[batchOffset + 2] = index + 2;
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
if (isInvert) {
|
||
for (k = 0, m = subIndices.length; k < m; k += 3) {
|
||
batchOffset = batchIndexCount + k;
|
||
batchIndices[batchOffset] = batchVertexCount + subIndices[k];
|
||
batchIndices[batchOffset + 1] = batchVertexCount + subIndices[k + 2];
|
||
batchIndices[batchOffset + 2] = batchVertexCount + subIndices[k + 1];
|
||
}
|
||
}
|
||
else {
|
||
for (k = 0, m = subIndices.length; k < m; k += 3) {
|
||
batchOffset = batchIndexCount + k;
|
||
batchIndices[batchOffset] = batchVertexCount + subIndices[k];
|
||
batchIndices[batchOffset + 1] = batchVertexCount + subIndices[k + 1];
|
||
batchIndices[batchOffset + 2] = batchVertexCount + subIndices[k + 2];
|
||
}
|
||
}
|
||
}
|
||
}
|
||
_flush(vertexCount, indexCount) {
|
||
var gl = Laya.LayaGL.instance;
|
||
this._vertexBuffer.setData(this._vertices.buffer, 0, 0, vertexCount * (this._bufferState.vertexDeclaration.vertexStride));
|
||
this._indexBuffer.setData(this._indices, 0, 0, indexCount);
|
||
gl.drawElements(gl.TRIANGLES, indexCount, gl.UNSIGNED_SHORT, 0);
|
||
}
|
||
_prepareRender(state) {
|
||
var element = state.renderElement;
|
||
var vertexDeclaration = element.vertexBatchVertexDeclaration;
|
||
this._bufferState = ILaya3D.MeshRenderDynamicBatchManager.instance._getBufferState(vertexDeclaration);
|
||
this._positionOffset = vertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_POSITION0)._offset / 4;
|
||
var normalElement = vertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_NORMAL0);
|
||
this._normalOffset = normalElement ? normalElement._offset / 4 : -1;
|
||
var colorElement = vertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_COLOR0);
|
||
this._colorOffset = colorElement ? colorElement._offset / 4 : -1;
|
||
var uv0Element = vertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_TEXTURECOORDINATE0);
|
||
this._uv0Offset = uv0Element ? uv0Element._offset / 4 : -1;
|
||
var uv1Element = vertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_TEXTURECOORDINATE1);
|
||
this._uv1Offset = uv1Element ? uv1Element._offset / 4 : -1;
|
||
var tangentElement = vertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_TANGENT0);
|
||
this._sTangentOffset = tangentElement ? tangentElement._offset / 4 : -1;
|
||
return true;
|
||
}
|
||
_render(context) {
|
||
this._bufferState.bind();
|
||
var element = context.renderElement;
|
||
var vertexDeclaration = element.vertexBatchVertexDeclaration;
|
||
var batchElements = element.vertexBatchElementList;
|
||
var batchVertexCount = 0;
|
||
var batchIndexCount = 0;
|
||
var renderBatchCount = 0;
|
||
var elementCount = batchElements.length;
|
||
var elements = batchElements.elements;
|
||
for (var i = 0; i < elementCount; i++) {
|
||
var subElement = elements[i];
|
||
var subMesh = subElement._geometry;
|
||
var indexCount = subMesh._indexCount;
|
||
if (batchIndexCount + indexCount > SubMeshDynamicBatch.maxIndicesCount) {
|
||
this._flush(batchVertexCount, batchIndexCount);
|
||
renderBatchCount++;
|
||
Laya.Stat.trianglesFaces += batchIndexCount / 3;
|
||
batchVertexCount = batchIndexCount = 0;
|
||
}
|
||
var transform = subElement._transform;
|
||
this._getBatchVertices(vertexDeclaration, this._vertices, batchVertexCount, subElement, subMesh);
|
||
this._getBatchIndices(this._indices, batchIndexCount, batchVertexCount, transform, subMesh, subElement._dynamicMultiSubMesh);
|
||
batchVertexCount += subElement._dynamicVertexCount;
|
||
batchIndexCount += indexCount;
|
||
}
|
||
this._flush(batchVertexCount, batchIndexCount);
|
||
renderBatchCount++;
|
||
Laya.Stat.renderBatches += renderBatchCount;
|
||
Laya.Stat.savedRenderBatches += elementCount - renderBatchCount;
|
||
Laya.Stat.trianglesFaces += batchIndexCount / 3;
|
||
}
|
||
}
|
||
SubMeshDynamicBatch.maxAllowVertexCount = 10;
|
||
SubMeshDynamicBatch.maxAllowAttribueCount = 900;
|
||
SubMeshDynamicBatch.maxIndicesCount = 32000;
|
||
|
||
class MeshRenderDynamicBatchManager extends DynamicBatchManager {
|
||
constructor() {
|
||
super();
|
||
this._instanceBatchOpaqueMarks = [];
|
||
this._vertexBatchOpaqueMarks = [];
|
||
this._cacheBufferStates = [];
|
||
this._updateCountMark = 0;
|
||
}
|
||
getInstanceBatchOpaquaMark(receiveShadow, materialID, subMeshID, invertFace) {
|
||
var instanceReceiveShadowMarks = (this._instanceBatchOpaqueMarks[receiveShadow ? 0 : 1]) || (this._instanceBatchOpaqueMarks[receiveShadow ? 0 : 1] = []);
|
||
var instanceMaterialMarks = (instanceReceiveShadowMarks[materialID]) || (instanceReceiveShadowMarks[materialID] = []);
|
||
var instancSubMeshMarks = (instanceMaterialMarks[subMeshID]) || (instanceMaterialMarks[subMeshID] = []);
|
||
return instancSubMeshMarks[invertFace ? 1 : 0] || (instancSubMeshMarks[invertFace ? 1 : 0] = new BatchMark());
|
||
}
|
||
getVertexBatchOpaquaMark(lightMapIndex, receiveShadow, materialID, verDecID) {
|
||
var dynLightMapMarks = (this._vertexBatchOpaqueMarks[lightMapIndex]) || (this._vertexBatchOpaqueMarks[lightMapIndex] = []);
|
||
var dynReceiveShadowMarks = (dynLightMapMarks[receiveShadow ? 0 : 1]) || (dynLightMapMarks[receiveShadow ? 0 : 1] = []);
|
||
var dynMaterialMarks = (dynReceiveShadowMarks[materialID]) || (dynReceiveShadowMarks[materialID] = []);
|
||
return dynMaterialMarks[verDecID] || (dynMaterialMarks[verDecID] = new BatchMark());
|
||
}
|
||
_getBufferState(vertexDeclaration) {
|
||
var bufferState = this._cacheBufferStates[vertexDeclaration.id];
|
||
if (!bufferState) {
|
||
var instance = SubMeshDynamicBatch.instance;
|
||
bufferState = new BufferState();
|
||
bufferState.bind();
|
||
var vertexBuffer = instance._vertexBuffer;
|
||
vertexBuffer.vertexDeclaration = vertexDeclaration;
|
||
bufferState.applyVertexBuffer(vertexBuffer);
|
||
bufferState.applyIndexBuffer(instance._indexBuffer);
|
||
bufferState.unBind();
|
||
this._cacheBufferStates[vertexDeclaration.id] = bufferState;
|
||
}
|
||
return bufferState;
|
||
}
|
||
_getBatchRenderElementFromPool() {
|
||
var renderElement = this._batchRenderElementPool[this._batchRenderElementPoolIndex++];
|
||
if (!renderElement) {
|
||
renderElement = new SubMeshRenderElement();
|
||
this._batchRenderElementPool[this._batchRenderElementPoolIndex - 1] = renderElement;
|
||
renderElement.vertexBatchElementList = new SingletonList();
|
||
renderElement.instanceBatchElementList = new SingletonList();
|
||
}
|
||
return renderElement;
|
||
}
|
||
_clear() {
|
||
super._clear();
|
||
this._updateCountMark++;
|
||
}
|
||
}
|
||
MeshRenderDynamicBatchManager.instance = new MeshRenderDynamicBatchManager();
|
||
|
||
class MeshSprite3D extends RenderableSprite3D {
|
||
constructor(mesh = null, name = null) {
|
||
super(name);
|
||
this._meshFilter = new MeshFilter(this);
|
||
this._render = new MeshRenderer(this);
|
||
(mesh) && (this._meshFilter.sharedMesh = mesh);
|
||
}
|
||
static __init__() {
|
||
MeshSprite3DShaderDeclaration.SHADERDEFINE_UV0 = Shader3D.getDefineByName("UV");
|
||
MeshSprite3DShaderDeclaration.SHADERDEFINE_COLOR = Shader3D.getDefineByName("COLOR");
|
||
MeshSprite3DShaderDeclaration.SHADERDEFINE_UV1 = Shader3D.getDefineByName("UV1");
|
||
MeshSprite3DShaderDeclaration.SHADERDEFINE_GPU_INSTANCE = Shader3D.getDefineByName("GPU_INSTANCE");
|
||
MeshSprite3DShaderDeclaration.SHADERDEFINE_SPECCUBE_BOX_PROJECTION = Shader3D.getDefineByName("SPECCUBE_BOX_PROJECTION");
|
||
StaticBatchManager._registerManager(MeshRenderStaticBatchManager.instance);
|
||
DynamicBatchManager._registerManager(MeshRenderDynamicBatchManager.instance);
|
||
}
|
||
get meshFilter() {
|
||
return this._meshFilter;
|
||
}
|
||
get meshRenderer() {
|
||
return this._render;
|
||
}
|
||
_parse(data, spriteMap) {
|
||
super._parse(data, spriteMap);
|
||
var render = this.meshRenderer;
|
||
var lightmapIndex = data.lightmapIndex;
|
||
(lightmapIndex != null) && (render.lightmapIndex = lightmapIndex);
|
||
var lightmapScaleOffsetArray = data.lightmapScaleOffset;
|
||
(lightmapScaleOffsetArray) && (render.lightmapScaleOffset = new Vector4(lightmapScaleOffsetArray[0], lightmapScaleOffsetArray[1], lightmapScaleOffsetArray[2], lightmapScaleOffsetArray[3]));
|
||
(data.meshPath != undefined) && (this.meshFilter.sharedMesh = Laya.Loader.getRes(data.meshPath));
|
||
(data.enableRender != undefined) && (render.enable = data.enableRender);
|
||
(data.receiveShadows != undefined) && (render.receiveShadow = data.receiveShadows);
|
||
(data.castShadow != undefined) && (render.castShadow = data.castShadow);
|
||
var materials = data.materials;
|
||
if (materials) {
|
||
var sharedMaterials = render.sharedMaterials;
|
||
var materialCount = materials.length;
|
||
sharedMaterials.length = materialCount;
|
||
for (var i = 0; i < materialCount; i++) {
|
||
sharedMaterials[i] = Laya.Loader.getRes(materials[i].path);
|
||
}
|
||
render.sharedMaterials = sharedMaterials;
|
||
}
|
||
}
|
||
_addToInitStaticBatchManager() {
|
||
if (this.meshFilter.sharedMesh)
|
||
MeshRenderStaticBatchManager.instance._addBatchSprite(this);
|
||
}
|
||
_cloneTo(destObject, rootSprite, dstSprite) {
|
||
var meshSprite3D = destObject;
|
||
meshSprite3D._meshFilter.sharedMesh = this._meshFilter.sharedMesh;
|
||
var meshRender = this._render;
|
||
var destMeshRender = meshSprite3D._render;
|
||
destMeshRender.enable = meshRender.enable;
|
||
destMeshRender.sharedMaterials = meshRender.sharedMaterials;
|
||
destMeshRender.castShadow = meshRender.castShadow;
|
||
var lightmapScaleOffset = meshRender.lightmapScaleOffset;
|
||
lightmapScaleOffset && (destMeshRender.lightmapScaleOffset = lightmapScaleOffset.clone());
|
||
destMeshRender.lightmapIndex = meshRender.lightmapIndex;
|
||
destMeshRender.receiveShadow = meshRender.receiveShadow;
|
||
destMeshRender.sortingFudge = meshRender.sortingFudge;
|
||
super._cloneTo(destObject, rootSprite, dstSprite);
|
||
}
|
||
destroy(destroyChild = true) {
|
||
if (this.destroyed)
|
||
return;
|
||
super.destroy(destroyChild);
|
||
this._meshFilter.destroy();
|
||
}
|
||
_create() {
|
||
return new MeshSprite3D();
|
||
}
|
||
}
|
||
|
||
class GradientMode {
|
||
}
|
||
GradientMode.Blend = 0;
|
||
GradientMode.Fixed = 1;
|
||
|
||
class Gradient {
|
||
constructor(maxColorRGBKeyCount, maxColorAlphaKeyCount) {
|
||
this._mode = 0;
|
||
this._maxColorRGBKeysCount = 0;
|
||
this._maxColorAlphaKeysCount = 0;
|
||
this._colorRGBKeysCount = 0;
|
||
this._colorAlphaKeysCount = 0;
|
||
this._alphaElements = null;
|
||
this._rgbElements = null;
|
||
this._maxColorRGBKeysCount = maxColorRGBKeyCount;
|
||
this._maxColorAlphaKeysCount = maxColorAlphaKeyCount;
|
||
this._rgbElements = new Float32Array(maxColorRGBKeyCount * 4);
|
||
this._alphaElements = new Float32Array(maxColorAlphaKeyCount * 2);
|
||
}
|
||
get mode() {
|
||
return this._mode;
|
||
}
|
||
set mode(value) {
|
||
this._mode = value;
|
||
}
|
||
get colorRGBKeysCount() {
|
||
return this._colorRGBKeysCount;
|
||
}
|
||
get colorAlphaKeysCount() {
|
||
return this._colorAlphaKeysCount;
|
||
}
|
||
get maxColorRGBKeysCount() {
|
||
return this._maxColorRGBKeysCount;
|
||
}
|
||
get maxColorAlphaKeysCount() {
|
||
return this._maxColorAlphaKeysCount;
|
||
}
|
||
addColorRGB(key, value) {
|
||
if (this._colorRGBKeysCount < this._maxColorRGBKeysCount) {
|
||
var offset = this._colorRGBKeysCount * 4;
|
||
this._rgbElements[offset] = key;
|
||
this._rgbElements[offset + 1] = value.r;
|
||
this._rgbElements[offset + 2] = value.g;
|
||
this._rgbElements[offset + 3] = value.b;
|
||
this._colorRGBKeysCount++;
|
||
}
|
||
else {
|
||
console.warn("Gradient:warning:data count must lessEqual than " + this._maxColorRGBKeysCount);
|
||
}
|
||
}
|
||
addColorAlpha(key, value) {
|
||
if (this._colorAlphaKeysCount < this._maxColorAlphaKeysCount) {
|
||
var offset = this._colorAlphaKeysCount * 2;
|
||
this._alphaElements[offset] = key;
|
||
this._alphaElements[offset + 1] = value;
|
||
this._colorAlphaKeysCount++;
|
||
}
|
||
else {
|
||
console.warn("Gradient:warning:data count must lessEqual than " + this._maxColorAlphaKeysCount);
|
||
}
|
||
}
|
||
updateColorRGB(index, key, value) {
|
||
if (index < this._colorRGBKeysCount) {
|
||
var offset = index * 4;
|
||
this._rgbElements[offset] = key;
|
||
this._rgbElements[offset + 1] = value.r;
|
||
this._rgbElements[offset + 2] = value.g;
|
||
this._rgbElements[offset + 3] = value.b;
|
||
}
|
||
else {
|
||
console.warn("Gradient:warning:index must lessEqual than colorRGBKeysCount:" + this._colorRGBKeysCount);
|
||
}
|
||
}
|
||
updateColorAlpha(index, key, value) {
|
||
if (index < this._colorAlphaKeysCount) {
|
||
var offset = index * 2;
|
||
this._alphaElements[offset] = key;
|
||
this._alphaElements[offset + 1] = value;
|
||
}
|
||
else {
|
||
console.warn("Gradient:warning:index must lessEqual than colorAlphaKeysCount:" + this._colorAlphaKeysCount);
|
||
}
|
||
}
|
||
evaluateColorRGB(lerpFactor, out, startSearchIndex = 0, reverseSearch = false) {
|
||
lerpFactor = Math.min(Math.max(lerpFactor, 0.0), 1.0);
|
||
var rgbElements = this._rgbElements;
|
||
var curIndex = startSearchIndex;
|
||
if (reverseSearch) {
|
||
for (var i = curIndex; i >= 0; i--) {
|
||
var offset = i * 4;
|
||
var left = rgbElements[offset];
|
||
if (lerpFactor === left) {
|
||
out.r = rgbElements[offset + 1];
|
||
out.g = rgbElements[offset + 2];
|
||
out.b = rgbElements[offset + 3];
|
||
return curIndex;
|
||
}
|
||
switch (this._mode) {
|
||
case GradientMode.Blend:
|
||
if (lerpFactor > left) {
|
||
var right = rgbElements[offset + 4];
|
||
if (lerpFactor > right)
|
||
throw "Gradient:wrong startSearchIndex.";
|
||
var diff = right - left;
|
||
var y1 = right - lerpFactor;
|
||
var y2 = lerpFactor - left;
|
||
out.r = (y1 * rgbElements[offset + 1] + y2 * rgbElements[offset + 5]) / diff;
|
||
out.g = (y1 * rgbElements[offset + 2] + y2 * rgbElements[offset + 6]) / diff;
|
||
out.b = (y1 * rgbElements[offset + 3] + y2 * rgbElements[offset + 7]) / diff;
|
||
return curIndex;
|
||
}
|
||
else {
|
||
curIndex--;
|
||
continue;
|
||
}
|
||
case GradientMode.Fixed:
|
||
if (lerpFactor > left) {
|
||
if (lerpFactor > rgbElements[offset + 4])
|
||
throw "Gradient:wrong startSearchIndex.";
|
||
out.r = rgbElements[offset + 5];
|
||
out.g = rgbElements[offset + 6];
|
||
out.b = rgbElements[offset + 7];
|
||
return curIndex;
|
||
}
|
||
else {
|
||
curIndex--;
|
||
continue;
|
||
}
|
||
default:
|
||
throw "Gradient:unknown mode.";
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
for (var i = 0, n = this._rgbElements.length; i < n; i++) {
|
||
offset = i * 4;
|
||
var right = rgbElements[offset];
|
||
if (lerpFactor === right) {
|
||
out.r = rgbElements[offset + 1];
|
||
out.g = rgbElements[offset + 2];
|
||
out.b = rgbElements[offset + 3];
|
||
return curIndex;
|
||
}
|
||
switch (this._mode) {
|
||
case GradientMode.Blend:
|
||
if (lerpFactor < right) {
|
||
var left = rgbElements[offset - 4];
|
||
if (lerpFactor < left)
|
||
throw "Gradient:wrong startSearchIndex.";
|
||
var diff = right - left;
|
||
var y1 = right - lerpFactor;
|
||
var y2 = lerpFactor - left;
|
||
out.r = (y1 * rgbElements[offset - 3] + y2 * rgbElements[offset + 1]) / diff;
|
||
out.g = (y1 * rgbElements[offset - 2] + y2 * rgbElements[offset + 2]) / diff;
|
||
out.b = (y1 * rgbElements[offset - 1] + y2 * rgbElements[offset + 3]) / diff;
|
||
return curIndex;
|
||
}
|
||
else {
|
||
curIndex++;
|
||
continue;
|
||
}
|
||
case GradientMode.Fixed:
|
||
if (lerpFactor < right) {
|
||
if (lerpFactor < rgbElements[offset - 4])
|
||
throw "Gradient:wrong startSearchIndex.";
|
||
out.r = rgbElements[offset + 1];
|
||
out.g = rgbElements[offset + 2];
|
||
out.b = rgbElements[offset + 3];
|
||
return curIndex;
|
||
}
|
||
else {
|
||
curIndex++;
|
||
continue;
|
||
}
|
||
default:
|
||
throw "Gradient:unknown mode.";
|
||
}
|
||
}
|
||
}
|
||
return curIndex;
|
||
}
|
||
evaluateColorAlpha(lerpFactor, outColor, startSearchIndex = 0, reverseSearch = false) {
|
||
lerpFactor = Math.min(Math.max(lerpFactor, 0.0), 1.0);
|
||
var alphaElements = this._alphaElements;
|
||
var curIndex = startSearchIndex;
|
||
if (reverseSearch) {
|
||
for (var i = curIndex; i >= 0; i--) {
|
||
var offset = i * 2;
|
||
var left = alphaElements[offset];
|
||
if (lerpFactor === left) {
|
||
outColor.a = alphaElements[offset + 1];
|
||
return curIndex;
|
||
}
|
||
switch (this._mode) {
|
||
case GradientMode.Blend:
|
||
if (lerpFactor > left) {
|
||
var right = alphaElements[offset + 2];
|
||
if (lerpFactor > right)
|
||
throw "Gradient:wrong startSearchIndex.";
|
||
var diff = right - left;
|
||
var x1 = right - lerpFactor;
|
||
var x2 = lerpFactor - left;
|
||
outColor.a = (x1 * alphaElements[offset + 1] + x2 * alphaElements[offset + 3]) / diff;
|
||
return curIndex;
|
||
}
|
||
else {
|
||
curIndex--;
|
||
continue;
|
||
}
|
||
case GradientMode.Fixed:
|
||
if (lerpFactor > left) {
|
||
if (lerpFactor > alphaElements[offset + 2])
|
||
throw "Gradient:wrong startSearchIndex.";
|
||
outColor.a = alphaElements[offset + 3];
|
||
return curIndex;
|
||
}
|
||
else {
|
||
curIndex--;
|
||
continue;
|
||
}
|
||
default:
|
||
throw "Gradient:unknown mode.";
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
for (var i = curIndex, n = this._alphaElements.length; i < n; i++) {
|
||
var offset = i * 2;
|
||
var right = alphaElements[offset];
|
||
if (lerpFactor === right) {
|
||
outColor.a = alphaElements[offset + 1];
|
||
return curIndex;
|
||
}
|
||
switch (this._mode) {
|
||
case GradientMode.Blend:
|
||
if (lerpFactor < right) {
|
||
var left = alphaElements[offset - 2];
|
||
if (lerpFactor < left)
|
||
throw "Gradient:wrong startSearchIndex.";
|
||
var diff = right - left;
|
||
var x1 = right - lerpFactor;
|
||
var x2 = lerpFactor - left;
|
||
outColor.a = (x1 * alphaElements[offset - 1] + x2 * alphaElements[offset + 1]) / diff;
|
||
return curIndex;
|
||
}
|
||
else {
|
||
curIndex++;
|
||
continue;
|
||
}
|
||
case GradientMode.Fixed:
|
||
if (lerpFactor < right) {
|
||
if (lerpFactor < alphaElements[offset - 2])
|
||
throw "Gradient:wrong startSearchIndex.";
|
||
outColor.a = alphaElements[offset + 1];
|
||
return curIndex;
|
||
}
|
||
else {
|
||
curIndex++;
|
||
continue;
|
||
}
|
||
default:
|
||
throw "Gradient:unknown mode.";
|
||
}
|
||
}
|
||
}
|
||
return curIndex;
|
||
}
|
||
cloneTo(destObject) {
|
||
var destGradientDataColor = destObject;
|
||
var i, n;
|
||
destGradientDataColor._colorAlphaKeysCount = this._colorAlphaKeysCount;
|
||
var destAlphaElements = destGradientDataColor._alphaElements;
|
||
for (i = 0, n = this._alphaElements.length; i < n; i++)
|
||
destAlphaElements[i] = this._alphaElements[i];
|
||
destGradientDataColor._colorRGBKeysCount = this._colorRGBKeysCount;
|
||
var destRGBElements = destGradientDataColor._rgbElements;
|
||
for (i = 0, n = this._rgbElements.length; i < n; i++)
|
||
destRGBElements[i] = this._rgbElements[i];
|
||
}
|
||
clone() {
|
||
var destGradientDataColor = new Gradient(this._maxColorRGBKeysCount, this._maxColorAlphaKeysCount);
|
||
this.cloneTo(destGradientDataColor);
|
||
return destGradientDataColor;
|
||
}
|
||
}
|
||
|
||
class Burst {
|
||
constructor(time, minCount, maxCount) {
|
||
this._time = time;
|
||
this._minCount = minCount;
|
||
this._maxCount = maxCount;
|
||
}
|
||
get time() {
|
||
return this._time;
|
||
}
|
||
get minCount() {
|
||
return this._minCount;
|
||
}
|
||
get maxCount() {
|
||
return this._maxCount;
|
||
}
|
||
cloneTo(destObject) {
|
||
var destBurst = destObject;
|
||
destBurst._time = this._time;
|
||
destBurst._minCount = this._minCount;
|
||
destBurst._maxCount = this._maxCount;
|
||
}
|
||
clone() {
|
||
var destBurst = new Burst(this._time, this._minCount, this._maxCount);
|
||
this.cloneTo(destBurst);
|
||
return destBurst;
|
||
}
|
||
}
|
||
|
||
class GradientColor {
|
||
constructor() {
|
||
this._type = 0;
|
||
this._constant = null;
|
||
this._constantMin = null;
|
||
this._constantMax = null;
|
||
this._gradient = null;
|
||
this._gradientMin = null;
|
||
this._gradientMax = null;
|
||
}
|
||
static createByConstant(constant) {
|
||
var gradientColor = new GradientColor();
|
||
gradientColor._type = 0;
|
||
gradientColor._constant = constant;
|
||
return gradientColor;
|
||
}
|
||
static createByGradient(gradient) {
|
||
var gradientColor = new GradientColor();
|
||
gradientColor._type = 1;
|
||
gradientColor._gradient = gradient;
|
||
return gradientColor;
|
||
}
|
||
static createByRandomTwoConstant(minConstant, maxConstant) {
|
||
var gradientColor = new GradientColor();
|
||
gradientColor._type = 2;
|
||
gradientColor._constantMin = minConstant;
|
||
gradientColor._constantMax = maxConstant;
|
||
return gradientColor;
|
||
}
|
||
static createByRandomTwoGradient(minGradient, maxGradient) {
|
||
var gradientColor = new GradientColor();
|
||
gradientColor._type = 3;
|
||
gradientColor._gradientMin = minGradient;
|
||
gradientColor._gradientMax = maxGradient;
|
||
return gradientColor;
|
||
}
|
||
get type() {
|
||
return this._type;
|
||
}
|
||
get constant() {
|
||
return this._constant;
|
||
}
|
||
get constantMin() {
|
||
return this._constantMin;
|
||
}
|
||
get constantMax() {
|
||
return this._constantMax;
|
||
}
|
||
get gradient() {
|
||
return this._gradient;
|
||
}
|
||
get gradientMin() {
|
||
return this._gradientMin;
|
||
}
|
||
get gradientMax() {
|
||
return this._gradientMax;
|
||
}
|
||
cloneTo(destObject) {
|
||
var destGradientColor = destObject;
|
||
destGradientColor._type = this._type;
|
||
this._constant.cloneTo(destGradientColor._constant);
|
||
this._constantMin.cloneTo(destGradientColor._constantMin);
|
||
this._constantMax.cloneTo(destGradientColor._constantMax);
|
||
this._gradient.cloneTo(destGradientColor._gradient);
|
||
this._gradientMin.cloneTo(destGradientColor._gradientMin);
|
||
this._gradientMax.cloneTo(destGradientColor._gradientMax);
|
||
}
|
||
clone() {
|
||
var destGradientColor = new GradientColor();
|
||
this.cloneTo(destGradientColor);
|
||
return destGradientColor;
|
||
}
|
||
}
|
||
|
||
class ColorOverLifetime {
|
||
constructor(color) {
|
||
this._color = color;
|
||
}
|
||
get color() {
|
||
return this._color;
|
||
}
|
||
cloneTo(destObject) {
|
||
var destColorOverLifetime = destObject;
|
||
this._color.cloneTo(destColorOverLifetime._color);
|
||
destColorOverLifetime.enable = this.enable;
|
||
}
|
||
clone() {
|
||
var destColor;
|
||
switch (this._color.type) {
|
||
case 0:
|
||
destColor = GradientColor.createByConstant(this._color.constant.clone());
|
||
break;
|
||
case 1:
|
||
destColor = GradientColor.createByGradient(this._color.gradient.clone());
|
||
break;
|
||
case 2:
|
||
destColor = GradientColor.createByRandomTwoConstant(this._color.constantMin.clone(), this._color.constantMax.clone());
|
||
break;
|
||
case 3:
|
||
destColor = GradientColor.createByRandomTwoGradient(this._color.gradientMin.clone(), this._color.gradientMax.clone());
|
||
break;
|
||
}
|
||
var destColorOverLifetime = new ColorOverLifetime(destColor);
|
||
destColorOverLifetime.enable = this.enable;
|
||
return destColorOverLifetime;
|
||
}
|
||
}
|
||
|
||
class FrameOverTime {
|
||
constructor() {
|
||
this._type = 0;
|
||
this._constant = 0;
|
||
this._overTime = null;
|
||
this._constantMin = 0;
|
||
this._constantMax = 0;
|
||
this._overTimeMin = null;
|
||
this._overTimeMax = null;
|
||
}
|
||
static createByConstant(constant = 0) {
|
||
var rotationOverLifetime = new FrameOverTime();
|
||
rotationOverLifetime._type = 0;
|
||
rotationOverLifetime._constant = constant;
|
||
return rotationOverLifetime;
|
||
}
|
||
static createByOverTime(overTime) {
|
||
var rotationOverLifetime = new FrameOverTime();
|
||
rotationOverLifetime._type = 1;
|
||
rotationOverLifetime._overTime = overTime;
|
||
return rotationOverLifetime;
|
||
}
|
||
static createByRandomTwoConstant(constantMin = 0, constantMax = 0) {
|
||
var rotationOverLifetime = new FrameOverTime();
|
||
rotationOverLifetime._type = 2;
|
||
rotationOverLifetime._constantMin = constantMin;
|
||
rotationOverLifetime._constantMax = constantMax;
|
||
return rotationOverLifetime;
|
||
}
|
||
static createByRandomTwoOverTime(gradientFrameMin, gradientFrameMax) {
|
||
var rotationOverLifetime = new FrameOverTime();
|
||
rotationOverLifetime._type = 3;
|
||
rotationOverLifetime._overTimeMin = gradientFrameMin;
|
||
rotationOverLifetime._overTimeMax = gradientFrameMax;
|
||
return rotationOverLifetime;
|
||
}
|
||
get type() {
|
||
return this._type;
|
||
}
|
||
get constant() {
|
||
return this._constant;
|
||
}
|
||
get frameOverTimeData() {
|
||
return this._overTime;
|
||
}
|
||
get constantMin() {
|
||
return this._constantMin;
|
||
}
|
||
get constantMax() {
|
||
return this._constantMax;
|
||
}
|
||
get frameOverTimeDataMin() {
|
||
return this._overTimeMin;
|
||
}
|
||
get frameOverTimeDataMax() {
|
||
return this._overTimeMax;
|
||
}
|
||
cloneTo(destObject) {
|
||
var destFrameOverTime = destObject;
|
||
destFrameOverTime._type = this._type;
|
||
destFrameOverTime._constant = this._constant;
|
||
(this._overTime) && (this._overTime.cloneTo(destFrameOverTime._overTime));
|
||
destFrameOverTime._constantMin = this._constantMin;
|
||
destFrameOverTime._constantMax = this._constantMax;
|
||
(this._overTimeMin) && (this._overTimeMin.cloneTo(destFrameOverTime._overTimeMin));
|
||
(this._overTimeMax) && (this._overTimeMax.cloneTo(destFrameOverTime._overTimeMax));
|
||
}
|
||
clone() {
|
||
var destFrameOverTime = new FrameOverTime();
|
||
this.cloneTo(destFrameOverTime);
|
||
return destFrameOverTime;
|
||
}
|
||
}
|
||
|
||
class GradientAngularVelocity {
|
||
constructor() {
|
||
this._type = 0;
|
||
this._separateAxes = false;
|
||
this._constant = 0;
|
||
this._constantSeparate = null;
|
||
this._gradient = null;
|
||
this._gradientX = null;
|
||
this._gradientY = null;
|
||
this._gradientZ = null;
|
||
this._gradientW = null;
|
||
this._constantMin = 0;
|
||
this._constantMax = 0;
|
||
this._constantMinSeparate = null;
|
||
this._constantMaxSeparate = null;
|
||
this._gradientMin = null;
|
||
this._gradientMax = null;
|
||
this._gradientXMin = null;
|
||
this._gradientXMax = null;
|
||
this._gradientYMin = null;
|
||
this._gradientYMax = null;
|
||
this._gradientZMin = null;
|
||
this._gradientZMax = null;
|
||
this._gradientWMin = null;
|
||
this._gradientWMax = null;
|
||
}
|
||
static createByConstant(constant) {
|
||
var gradientAngularVelocity = new GradientAngularVelocity();
|
||
gradientAngularVelocity._type = 0;
|
||
gradientAngularVelocity._separateAxes = false;
|
||
gradientAngularVelocity._constant = constant;
|
||
return gradientAngularVelocity;
|
||
}
|
||
static createByConstantSeparate(separateConstant) {
|
||
var gradientAngularVelocity = new GradientAngularVelocity();
|
||
gradientAngularVelocity._type = 0;
|
||
gradientAngularVelocity._separateAxes = true;
|
||
gradientAngularVelocity._constantSeparate = separateConstant;
|
||
return gradientAngularVelocity;
|
||
}
|
||
static createByGradient(gradient) {
|
||
var gradientAngularVelocity = new GradientAngularVelocity();
|
||
gradientAngularVelocity._type = 1;
|
||
gradientAngularVelocity._separateAxes = false;
|
||
gradientAngularVelocity._gradient = gradient;
|
||
return gradientAngularVelocity;
|
||
}
|
||
static createByGradientSeparate(gradientX, gradientY, gradientZ) {
|
||
var gradientAngularVelocity = new GradientAngularVelocity();
|
||
gradientAngularVelocity._type = 1;
|
||
gradientAngularVelocity._separateAxes = true;
|
||
gradientAngularVelocity._gradientX = gradientX;
|
||
gradientAngularVelocity._gradientY = gradientY;
|
||
gradientAngularVelocity._gradientZ = gradientZ;
|
||
return gradientAngularVelocity;
|
||
}
|
||
static createByRandomTwoConstant(constantMin, constantMax) {
|
||
var gradientAngularVelocity = new GradientAngularVelocity();
|
||
gradientAngularVelocity._type = 2;
|
||
gradientAngularVelocity._separateAxes = false;
|
||
gradientAngularVelocity._constantMin = constantMin;
|
||
gradientAngularVelocity._constantMax = constantMax;
|
||
return gradientAngularVelocity;
|
||
}
|
||
static createByRandomTwoConstantSeparate(separateConstantMin, separateConstantMax) {
|
||
var gradientAngularVelocity = new GradientAngularVelocity();
|
||
gradientAngularVelocity._type = 2;
|
||
gradientAngularVelocity._separateAxes = true;
|
||
gradientAngularVelocity._constantMinSeparate = separateConstantMin;
|
||
gradientAngularVelocity._constantMaxSeparate = separateConstantMax;
|
||
return gradientAngularVelocity;
|
||
}
|
||
static createByRandomTwoGradient(gradientMin, gradientMax) {
|
||
var gradientAngularVelocity = new GradientAngularVelocity();
|
||
gradientAngularVelocity._type = 3;
|
||
gradientAngularVelocity._separateAxes = false;
|
||
gradientAngularVelocity._gradientMin = gradientMin;
|
||
gradientAngularVelocity._gradientMax = gradientMax;
|
||
return gradientAngularVelocity;
|
||
}
|
||
static createByRandomTwoGradientSeparate(gradientXMin, gradientXMax, gradientYMin, gradientYMax, gradientZMin, gradientZMax, gradientWMin, gradientWMax) {
|
||
var gradientAngularVelocity = new GradientAngularVelocity();
|
||
gradientAngularVelocity._type = 3;
|
||
gradientAngularVelocity._separateAxes = true;
|
||
gradientAngularVelocity._gradientXMin = gradientXMin;
|
||
gradientAngularVelocity._gradientXMax = gradientXMax;
|
||
gradientAngularVelocity._gradientYMin = gradientYMin;
|
||
gradientAngularVelocity._gradientYMax = gradientYMax;
|
||
gradientAngularVelocity._gradientZMin = gradientZMin;
|
||
gradientAngularVelocity._gradientZMax = gradientZMax;
|
||
gradientAngularVelocity._gradientWMin = gradientWMin;
|
||
gradientAngularVelocity._gradientWMax = gradientWMax;
|
||
return gradientAngularVelocity;
|
||
}
|
||
get type() {
|
||
return this._type;
|
||
}
|
||
get separateAxes() {
|
||
return this._separateAxes;
|
||
}
|
||
get constant() {
|
||
return this._constant;
|
||
}
|
||
get constantSeparate() {
|
||
return this._constantSeparate;
|
||
}
|
||
get gradient() {
|
||
return this._gradient;
|
||
}
|
||
get gradientX() {
|
||
return this._gradientX;
|
||
}
|
||
get gradientY() {
|
||
return this._gradientY;
|
||
}
|
||
get gradientZ() {
|
||
return this._gradientZ;
|
||
}
|
||
get gradientW() {
|
||
return this._gradientW;
|
||
}
|
||
get constantMin() {
|
||
return this._constantMin;
|
||
}
|
||
get constantMax() {
|
||
return this._constantMax;
|
||
}
|
||
get constantMinSeparate() {
|
||
return this._constantMinSeparate;
|
||
}
|
||
get constantMaxSeparate() {
|
||
return this._constantMaxSeparate;
|
||
}
|
||
get gradientMin() {
|
||
return this._gradientMin;
|
||
}
|
||
get gradientMax() {
|
||
return this._gradientMax;
|
||
}
|
||
get gradientXMin() {
|
||
return this._gradientXMin;
|
||
}
|
||
get gradientXMax() {
|
||
return this._gradientXMax;
|
||
}
|
||
get gradientYMin() {
|
||
return this._gradientYMin;
|
||
}
|
||
get gradientYMax() {
|
||
return this._gradientYMax;
|
||
}
|
||
get gradientZMin() {
|
||
return this._gradientZMin;
|
||
}
|
||
get gradientZMax() {
|
||
return this._gradientZMax;
|
||
}
|
||
get gradientWMin() {
|
||
return this._gradientWMin;
|
||
}
|
||
get gradientWMax() {
|
||
return this._gradientWMax;
|
||
}
|
||
cloneTo(destObject) {
|
||
var destGradientAngularVelocity = destObject;
|
||
destGradientAngularVelocity._type = this._type;
|
||
destGradientAngularVelocity._separateAxes = this._separateAxes;
|
||
destGradientAngularVelocity._constant = this._constant;
|
||
this._constantSeparate.cloneTo(destGradientAngularVelocity._constantSeparate);
|
||
this._gradient.cloneTo(destGradientAngularVelocity._gradient);
|
||
this._gradientX.cloneTo(destGradientAngularVelocity._gradientX);
|
||
this._gradientY.cloneTo(destGradientAngularVelocity._gradientY);
|
||
this._gradientZ.cloneTo(destGradientAngularVelocity._gradientZ);
|
||
destGradientAngularVelocity._constantMin = this._constantMin;
|
||
destGradientAngularVelocity._constantMax = this._constantMax;
|
||
this._constantMinSeparate.cloneTo(destGradientAngularVelocity._constantMinSeparate);
|
||
this._constantMaxSeparate.cloneTo(destGradientAngularVelocity._constantMaxSeparate);
|
||
this._gradientMin.cloneTo(destGradientAngularVelocity._gradientMin);
|
||
this._gradientMax.cloneTo(destGradientAngularVelocity._gradientMax);
|
||
this._gradientXMin.cloneTo(destGradientAngularVelocity._gradientXMin);
|
||
this._gradientXMax.cloneTo(destGradientAngularVelocity._gradientXMax);
|
||
this._gradientYMin.cloneTo(destGradientAngularVelocity._gradientYMin);
|
||
this._gradientYMax.cloneTo(destGradientAngularVelocity._gradientYMax);
|
||
this._gradientZMin.cloneTo(destGradientAngularVelocity._gradientZMin);
|
||
this._gradientZMax.cloneTo(destGradientAngularVelocity._gradientZMax);
|
||
}
|
||
clone() {
|
||
var destGradientAngularVelocity = new GradientAngularVelocity();
|
||
this.cloneTo(destGradientAngularVelocity);
|
||
return destGradientAngularVelocity;
|
||
}
|
||
}
|
||
|
||
class GradientDataInt {
|
||
constructor() {
|
||
this._currentLength = 0;
|
||
this._elements = new Float32Array(8);
|
||
}
|
||
get gradientCount() {
|
||
return this._currentLength / 2;
|
||
}
|
||
add(key, value) {
|
||
if (this._currentLength < 8) {
|
||
if ((this._currentLength === 6) && ((key !== 1))) {
|
||
key = 1;
|
||
console.log("Warning:the forth key is be force set to 1.");
|
||
}
|
||
this._elements[this._currentLength++] = key;
|
||
this._elements[this._currentLength++] = value;
|
||
}
|
||
else {
|
||
console.log("Warning:data count must lessEqual than 4");
|
||
}
|
||
}
|
||
cloneTo(destObject) {
|
||
var destGradientDataInt = destObject;
|
||
destGradientDataInt._currentLength = this._currentLength;
|
||
var destElements = destGradientDataInt._elements;
|
||
for (var i = 0, n = this._elements.length; i < n; i++) {
|
||
destElements[i] = this._elements[i];
|
||
}
|
||
}
|
||
clone() {
|
||
var destGradientDataInt = new GradientDataInt();
|
||
this.cloneTo(destGradientDataInt);
|
||
return destGradientDataInt;
|
||
}
|
||
}
|
||
|
||
class GradientDataNumber {
|
||
constructor() {
|
||
this._currentLength = 0;
|
||
this._elements = new Float32Array(8);
|
||
}
|
||
get gradientCount() {
|
||
return this._currentLength / 2;
|
||
}
|
||
add(key, value) {
|
||
if (this._currentLength < 8) {
|
||
if ((this._currentLength === 6) && ((key !== 1))) {
|
||
key = 1;
|
||
console.log("GradientDataNumber warning:the forth key is be force set to 1.");
|
||
}
|
||
this._elements[this._currentLength++] = key;
|
||
this._elements[this._currentLength++] = value;
|
||
}
|
||
else {
|
||
console.log("GradientDataNumber warning:data count must lessEqual than 4");
|
||
}
|
||
}
|
||
getKeyByIndex(index) {
|
||
return this._elements[index * 2];
|
||
}
|
||
getValueByIndex(index) {
|
||
return this._elements[index * 2 + 1];
|
||
}
|
||
getAverageValue() {
|
||
var total = 0;
|
||
var count = 0;
|
||
for (var i = 0, n = this._currentLength - 2; i < n; i += 2) {
|
||
var subValue = this._elements[i + 1];
|
||
subValue += this._elements[i + 3];
|
||
subValue = subValue * (this._elements[i + 2] - this._elements[i]);
|
||
total += subValue;
|
||
count++;
|
||
}
|
||
return total / count;
|
||
}
|
||
cloneTo(destObject) {
|
||
var destGradientDataNumber = destObject;
|
||
destGradientDataNumber._currentLength = this._currentLength;
|
||
var destElements = destGradientDataNumber._elements;
|
||
for (var i = 0, n = this._elements.length; i < n; i++)
|
||
destElements[i] = this._elements[i];
|
||
}
|
||
clone() {
|
||
var destGradientDataNumber = new GradientDataNumber();
|
||
this.cloneTo(destGradientDataNumber);
|
||
return destGradientDataNumber;
|
||
}
|
||
}
|
||
|
||
class GradientSize {
|
||
constructor() {
|
||
this._type = 0;
|
||
this._separateAxes = false;
|
||
this._gradient = null;
|
||
this._gradientX = null;
|
||
this._gradientY = null;
|
||
this._gradientZ = null;
|
||
this._constantMin = 0;
|
||
this._constantMax = 0;
|
||
this._constantMinSeparate = null;
|
||
this._constantMaxSeparate = null;
|
||
this._gradientMin = null;
|
||
this._gradientMax = null;
|
||
this._gradientXMin = null;
|
||
this._gradientXMax = null;
|
||
this._gradientYMin = null;
|
||
this._gradientYMax = null;
|
||
this._gradientZMin = null;
|
||
this._gradientZMax = null;
|
||
}
|
||
static createByGradient(gradient) {
|
||
var gradientSize = new GradientSize();
|
||
gradientSize._type = 0;
|
||
gradientSize._separateAxes = false;
|
||
gradientSize._gradient = gradient;
|
||
return gradientSize;
|
||
}
|
||
static createByGradientSeparate(gradientX, gradientY, gradientZ) {
|
||
var gradientSize = new GradientSize();
|
||
gradientSize._type = 0;
|
||
gradientSize._separateAxes = true;
|
||
gradientSize._gradientX = gradientX;
|
||
gradientSize._gradientY = gradientY;
|
||
gradientSize._gradientZ = gradientZ;
|
||
return gradientSize;
|
||
}
|
||
static createByRandomTwoConstant(constantMin, constantMax) {
|
||
var gradientSize = new GradientSize();
|
||
gradientSize._type = 1;
|
||
gradientSize._separateAxes = false;
|
||
gradientSize._constantMin = constantMin;
|
||
gradientSize._constantMax = constantMax;
|
||
return gradientSize;
|
||
}
|
||
static createByRandomTwoConstantSeparate(constantMinSeparate, constantMaxSeparate) {
|
||
var gradientSize = new GradientSize();
|
||
gradientSize._type = 1;
|
||
gradientSize._separateAxes = true;
|
||
gradientSize._constantMinSeparate = constantMinSeparate;
|
||
gradientSize._constantMaxSeparate = constantMaxSeparate;
|
||
return gradientSize;
|
||
}
|
||
static createByRandomTwoGradient(gradientMin, gradientMax) {
|
||
var gradientSize = new GradientSize();
|
||
gradientSize._type = 2;
|
||
gradientSize._separateAxes = false;
|
||
gradientSize._gradientMin = gradientMin;
|
||
gradientSize._gradientMax = gradientMax;
|
||
return gradientSize;
|
||
}
|
||
static createByRandomTwoGradientSeparate(gradientXMin, gradientXMax, gradientYMin, gradientYMax, gradientZMin, gradientZMax) {
|
||
var gradientSize = new GradientSize();
|
||
gradientSize._type = 2;
|
||
gradientSize._separateAxes = true;
|
||
gradientSize._gradientXMin = gradientXMin;
|
||
gradientSize._gradientXMax = gradientXMax;
|
||
gradientSize._gradientYMin = gradientYMin;
|
||
gradientSize._gradientYMax = gradientYMax;
|
||
gradientSize._gradientZMin = gradientZMin;
|
||
gradientSize._gradientZMax = gradientZMax;
|
||
return gradientSize;
|
||
}
|
||
get type() {
|
||
return this._type;
|
||
}
|
||
get separateAxes() {
|
||
return this._separateAxes;
|
||
}
|
||
get gradient() {
|
||
return this._gradient;
|
||
}
|
||
get gradientX() {
|
||
return this._gradientX;
|
||
}
|
||
get gradientY() {
|
||
return this._gradientY;
|
||
}
|
||
get gradientZ() {
|
||
return this._gradientZ;
|
||
}
|
||
get constantMin() {
|
||
return this._constantMin;
|
||
}
|
||
get constantMax() {
|
||
return this._constantMax;
|
||
}
|
||
get constantMinSeparate() {
|
||
return this._constantMinSeparate;
|
||
}
|
||
get constantMaxSeparate() {
|
||
return this._constantMaxSeparate;
|
||
}
|
||
get gradientMin() {
|
||
return this._gradientMin;
|
||
}
|
||
get gradientMax() {
|
||
return this._gradientMax;
|
||
}
|
||
get gradientXMin() {
|
||
return this._gradientXMin;
|
||
}
|
||
get gradientXMax() {
|
||
return this._gradientXMax;
|
||
}
|
||
get gradientYMin() {
|
||
return this._gradientYMin;
|
||
}
|
||
get gradientYMax() {
|
||
return this._gradientYMax;
|
||
}
|
||
get gradientZMin() {
|
||
return this._gradientZMin;
|
||
}
|
||
get gradientZMax() {
|
||
return this._gradientZMax;
|
||
}
|
||
getMaxSizeInGradient(meshMode = false) {
|
||
var i, n;
|
||
var maxSize = -Number.MAX_VALUE;
|
||
switch (this._type) {
|
||
case 0:
|
||
if (this._separateAxes) {
|
||
for (i = 0, n = this._gradientX.gradientCount; i < n; i++)
|
||
maxSize = Math.max(maxSize, this._gradientX.getValueByIndex(i));
|
||
for (i = 0, n = this._gradientY.gradientCount; i < n; i++)
|
||
maxSize = Math.max(maxSize, this._gradientY.getValueByIndex(i));
|
||
if (meshMode) {
|
||
for (i = 0, n = this._gradientZ.gradientCount; i < n; i++) {
|
||
maxSize = Math.max(maxSize, this._gradientZ.getValueByIndex(i));
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
for (i = 0, n = this._gradient.gradientCount; i < n; i++)
|
||
maxSize = Math.max(maxSize, this._gradient.getValueByIndex(i));
|
||
}
|
||
break;
|
||
case 1:
|
||
if (this._separateAxes) {
|
||
maxSize = Math.max(this._constantMinSeparate.x, this._constantMaxSeparate.x);
|
||
maxSize = Math.max(maxSize, this._constantMinSeparate.y);
|
||
if (meshMode) {
|
||
maxSize = maxSize = Math.max(maxSize, this._constantMaxSeparate.z);
|
||
}
|
||
}
|
||
else {
|
||
maxSize = Math.max(this._constantMin, this._constantMax);
|
||
}
|
||
break;
|
||
case 2:
|
||
if (this._separateAxes) {
|
||
for (i = 0, n = this._gradientXMin.gradientCount; i < n; i++)
|
||
maxSize = Math.max(maxSize, this._gradientXMin.getValueByIndex(i));
|
||
for (i = 0, n = this._gradientXMax.gradientCount; i < n; i++)
|
||
maxSize = Math.max(maxSize, this._gradientXMax.getValueByIndex(i));
|
||
for (i = 0, n = this._gradientYMin.gradientCount; i < n; i++)
|
||
maxSize = Math.max(maxSize, this._gradientYMin.getValueByIndex(i));
|
||
for (i = 0, n = this._gradientZMax.gradientCount; i < n; i++)
|
||
maxSize = Math.max(maxSize, this._gradientZMax.getValueByIndex(i));
|
||
if (meshMode) {
|
||
for (i = 0, n = this._gradientZMin.gradientCount; i < n; i++) {
|
||
maxSize = Math.max(maxSize, this._gradientZMin.getValueByIndex(i));
|
||
}
|
||
for (i = 0, n = this._gradientZMax.gradientCount; i < n; i++) {
|
||
maxSize = Math.max(maxSize, this._gradientZMax.getValueByIndex(i));
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
for (i = 0, n = this._gradientMin.gradientCount; i < n; i++)
|
||
maxSize = Math.max(maxSize, this._gradientMin.getValueByIndex(i));
|
||
for (i = 0, n = this._gradientMax.gradientCount; i < n; i++)
|
||
maxSize = Math.max(maxSize, this._gradientMax.getValueByIndex(i));
|
||
}
|
||
break;
|
||
}
|
||
return maxSize;
|
||
}
|
||
cloneTo(destObject) {
|
||
var destGradientSize = destObject;
|
||
destGradientSize._type = this._type;
|
||
destGradientSize._separateAxes = this._separateAxes;
|
||
this._gradient.cloneTo(destGradientSize._gradient);
|
||
this._gradientX.cloneTo(destGradientSize._gradientX);
|
||
this._gradientY.cloneTo(destGradientSize._gradientY);
|
||
this._gradientZ.cloneTo(destGradientSize._gradientZ);
|
||
destGradientSize._constantMin = this._constantMin;
|
||
destGradientSize._constantMax = this._constantMax;
|
||
this._constantMinSeparate.cloneTo(destGradientSize._constantMinSeparate);
|
||
this._constantMaxSeparate.cloneTo(destGradientSize._constantMaxSeparate);
|
||
this._gradientMin.cloneTo(destGradientSize._gradientMin);
|
||
this._gradientMax.cloneTo(destGradientSize._gradientMax);
|
||
this._gradientXMin.cloneTo(destGradientSize._gradientXMin);
|
||
this._gradientXMax.cloneTo(destGradientSize._gradientXMax);
|
||
this._gradientYMin.cloneTo(destGradientSize._gradientYMin);
|
||
this._gradientYMax.cloneTo(destGradientSize._gradientYMax);
|
||
this._gradientZMin.cloneTo(destGradientSize._gradientZMin);
|
||
this._gradientZMax.cloneTo(destGradientSize._gradientZMax);
|
||
}
|
||
clone() {
|
||
var destGradientSize = new GradientSize();
|
||
this.cloneTo(destGradientSize);
|
||
return destGradientSize;
|
||
}
|
||
}
|
||
|
||
class GradientVelocity {
|
||
constructor() {
|
||
this._type = 0;
|
||
this._constant = null;
|
||
this._gradientX = null;
|
||
this._gradientY = null;
|
||
this._gradientZ = null;
|
||
this._constantMin = null;
|
||
this._constantMax = null;
|
||
this._gradientXMin = null;
|
||
this._gradientXMax = null;
|
||
this._gradientYMin = null;
|
||
this._gradientYMax = null;
|
||
this._gradientZMin = null;
|
||
this._gradientZMax = null;
|
||
}
|
||
static createByConstant(constant) {
|
||
var gradientVelocity = new GradientVelocity();
|
||
gradientVelocity._type = 0;
|
||
gradientVelocity._constant = constant;
|
||
return gradientVelocity;
|
||
}
|
||
static createByGradient(gradientX, gradientY, gradientZ) {
|
||
var gradientVelocity = new GradientVelocity();
|
||
gradientVelocity._type = 1;
|
||
gradientVelocity._gradientX = gradientX;
|
||
gradientVelocity._gradientY = gradientY;
|
||
gradientVelocity._gradientZ = gradientZ;
|
||
return gradientVelocity;
|
||
}
|
||
static createByRandomTwoConstant(constantMin, constantMax) {
|
||
var gradientVelocity = new GradientVelocity();
|
||
gradientVelocity._type = 2;
|
||
gradientVelocity._constantMin = constantMin;
|
||
gradientVelocity._constantMax = constantMax;
|
||
return gradientVelocity;
|
||
}
|
||
static createByRandomTwoGradient(gradientXMin, gradientXMax, gradientYMin, gradientYMax, gradientZMin, gradientZMax) {
|
||
var gradientVelocity = new GradientVelocity();
|
||
gradientVelocity._type = 3;
|
||
gradientVelocity._gradientXMin = gradientXMin;
|
||
gradientVelocity._gradientXMax = gradientXMax;
|
||
gradientVelocity._gradientYMin = gradientYMin;
|
||
gradientVelocity._gradientYMax = gradientYMax;
|
||
gradientVelocity._gradientZMin = gradientZMin;
|
||
gradientVelocity._gradientZMax = gradientZMax;
|
||
return gradientVelocity;
|
||
}
|
||
get type() {
|
||
return this._type;
|
||
}
|
||
get constant() {
|
||
return this._constant;
|
||
}
|
||
get gradientX() {
|
||
return this._gradientX;
|
||
}
|
||
get gradientY() {
|
||
return this._gradientY;
|
||
}
|
||
get gradientZ() {
|
||
return this._gradientZ;
|
||
}
|
||
get constantMin() {
|
||
return this._constantMin;
|
||
}
|
||
get constantMax() {
|
||
return this._constantMax;
|
||
}
|
||
get gradientXMin() {
|
||
return this._gradientXMin;
|
||
}
|
||
get gradientXMax() {
|
||
return this._gradientXMax;
|
||
}
|
||
get gradientYMin() {
|
||
return this._gradientYMin;
|
||
}
|
||
get gradientYMax() {
|
||
return this._gradientYMax;
|
||
}
|
||
get gradientZMin() {
|
||
return this._gradientZMin;
|
||
}
|
||
get gradientZMax() {
|
||
return this._gradientZMax;
|
||
}
|
||
cloneTo(destObject) {
|
||
var destGradientVelocity = destObject;
|
||
destGradientVelocity._type = this._type;
|
||
this._constant.cloneTo(destGradientVelocity._constant);
|
||
this._gradientX.cloneTo(destGradientVelocity._gradientX);
|
||
this._gradientY.cloneTo(destGradientVelocity._gradientY);
|
||
this._gradientZ.cloneTo(destGradientVelocity._gradientZ);
|
||
this._constantMin.cloneTo(destGradientVelocity._constantMin);
|
||
this._constantMax.cloneTo(destGradientVelocity._constantMax);
|
||
this._gradientXMin.cloneTo(destGradientVelocity._gradientXMin);
|
||
this._gradientXMax.cloneTo(destGradientVelocity._gradientXMax);
|
||
this._gradientYMin.cloneTo(destGradientVelocity._gradientYMin);
|
||
this._gradientYMax.cloneTo(destGradientVelocity._gradientYMax);
|
||
this._gradientZMin.cloneTo(destGradientVelocity._gradientZMin);
|
||
this._gradientZMax.cloneTo(destGradientVelocity._gradientZMax);
|
||
}
|
||
clone() {
|
||
var destGradientVelocity = new GradientVelocity();
|
||
this.cloneTo(destGradientVelocity);
|
||
return destGradientVelocity;
|
||
}
|
||
}
|
||
|
||
class RotationOverLifetime {
|
||
constructor(angularVelocity) {
|
||
this._angularVelocity = angularVelocity;
|
||
}
|
||
get angularVelocity() {
|
||
return this._angularVelocity;
|
||
}
|
||
cloneTo(destObject) {
|
||
var destRotationOverLifetime = destObject;
|
||
this._angularVelocity.cloneTo(destRotationOverLifetime._angularVelocity);
|
||
destRotationOverLifetime.enable = this.enable;
|
||
}
|
||
clone() {
|
||
var destAngularVelocity;
|
||
switch (this._angularVelocity.type) {
|
||
case 0:
|
||
if (this._angularVelocity.separateAxes)
|
||
destAngularVelocity = GradientAngularVelocity.createByConstantSeparate(this._angularVelocity.constantSeparate.clone());
|
||
else
|
||
destAngularVelocity = GradientAngularVelocity.createByConstant(this._angularVelocity.constant);
|
||
break;
|
||
case 1:
|
||
if (this._angularVelocity.separateAxes)
|
||
destAngularVelocity = GradientAngularVelocity.createByGradientSeparate(this._angularVelocity.gradientX.clone(), this._angularVelocity.gradientY.clone(), this._angularVelocity.gradientZ.clone());
|
||
else
|
||
destAngularVelocity = GradientAngularVelocity.createByGradient(this._angularVelocity.gradient.clone());
|
||
break;
|
||
case 2:
|
||
if (this._angularVelocity.separateAxes)
|
||
destAngularVelocity = GradientAngularVelocity.createByRandomTwoConstantSeparate(this._angularVelocity.constantMinSeparate.clone(), this._angularVelocity.constantMaxSeparate.clone());
|
||
else
|
||
destAngularVelocity = GradientAngularVelocity.createByRandomTwoConstant(this._angularVelocity.constantMin, this._angularVelocity.constantMax);
|
||
break;
|
||
case 3:
|
||
if (this._angularVelocity.separateAxes)
|
||
destAngularVelocity = GradientAngularVelocity.createByRandomTwoGradientSeparate(this._angularVelocity.gradientXMin.clone(), this._angularVelocity.gradientYMin.clone(), this._angularVelocity.gradientZMin.clone(), this._angularVelocity.gradientWMin.clone(), this._angularVelocity.gradientXMax.clone(), this._angularVelocity.gradientYMax.clone(), this._angularVelocity.gradientZMax.clone(), this._angularVelocity.gradientWMax.clone());
|
||
else
|
||
destAngularVelocity = GradientAngularVelocity.createByRandomTwoGradient(this._angularVelocity.gradientMin.clone(), this._angularVelocity.gradientMax.clone());
|
||
break;
|
||
}
|
||
var destRotationOverLifetime = new RotationOverLifetime(destAngularVelocity);
|
||
destRotationOverLifetime.enable = this.enable;
|
||
return destRotationOverLifetime;
|
||
}
|
||
}
|
||
|
||
(function (ParticleSystemShapeType) {
|
||
ParticleSystemShapeType[ParticleSystemShapeType["Box"] = 0] = "Box";
|
||
ParticleSystemShapeType[ParticleSystemShapeType["Circle"] = 1] = "Circle";
|
||
ParticleSystemShapeType[ParticleSystemShapeType["Cone"] = 2] = "Cone";
|
||
ParticleSystemShapeType[ParticleSystemShapeType["Hemisphere"] = 3] = "Hemisphere";
|
||
ParticleSystemShapeType[ParticleSystemShapeType["Sphere"] = 4] = "Sphere";
|
||
})(exports.ParticleSystemShapeType || (exports.ParticleSystemShapeType = {}));
|
||
class BaseShape {
|
||
constructor() {
|
||
this.enable = true;
|
||
this.randomDirection = 0;
|
||
}
|
||
_getShapeBoundBox(boundBox) {
|
||
throw new Error("BaseShape: must override it.");
|
||
}
|
||
_getSpeedBoundBox(boundBox) {
|
||
throw new Error("BaseShape: must override it.");
|
||
}
|
||
generatePositionAndDirection(position, direction, rand = null, randomSeeds = null) {
|
||
throw new Error("BaseShape: must override it.");
|
||
}
|
||
_calculateProceduralBounds(boundBox, emitterPosScale, minMaxBounds) {
|
||
this._getShapeBoundBox(boundBox);
|
||
var min = boundBox.min;
|
||
var max = boundBox.max;
|
||
Vector3.multiply(min, emitterPosScale, min);
|
||
Vector3.multiply(max, emitterPosScale, max);
|
||
var speedBounds = new BoundBox(new Vector3(), new Vector3());
|
||
if (this.randomDirection) {
|
||
speedBounds.min = new Vector3(-1, -1, -1);
|
||
speedBounds.max = new Vector3(1, 1, 1);
|
||
}
|
||
else {
|
||
this._getSpeedBoundBox(speedBounds);
|
||
}
|
||
var maxSpeedBound = new BoundBox(new Vector3(), new Vector3());
|
||
var maxSpeedMin = maxSpeedBound.min;
|
||
var maxSpeedMax = maxSpeedBound.max;
|
||
Vector3.scale(speedBounds.min, minMaxBounds.y, maxSpeedMin);
|
||
Vector3.scale(speedBounds.max, minMaxBounds.y, maxSpeedMax);
|
||
Vector3.add(boundBox.min, maxSpeedMin, maxSpeedMin);
|
||
Vector3.add(boundBox.max, maxSpeedMax, maxSpeedMax);
|
||
Vector3.min(boundBox.min, maxSpeedMin, boundBox.min);
|
||
Vector3.max(boundBox.max, maxSpeedMin, boundBox.max);
|
||
var minSpeedBound = new BoundBox(new Vector3(), new Vector3());
|
||
var minSpeedMin = minSpeedBound.min;
|
||
var minSpeedMax = minSpeedBound.max;
|
||
Vector3.scale(speedBounds.min, minMaxBounds.x, minSpeedMin);
|
||
Vector3.scale(speedBounds.max, minMaxBounds.x, minSpeedMax);
|
||
Vector3.min(minSpeedBound.min, minSpeedMax, maxSpeedMin);
|
||
Vector3.max(minSpeedBound.min, minSpeedMax, maxSpeedMax);
|
||
Vector3.min(boundBox.min, maxSpeedMin, boundBox.min);
|
||
Vector3.max(boundBox.max, maxSpeedMin, boundBox.max);
|
||
}
|
||
cloneTo(destObject) {
|
||
var destShape = destObject;
|
||
destShape.enable = this.enable;
|
||
}
|
||
clone() {
|
||
var destShape = new BaseShape();
|
||
this.cloneTo(destShape);
|
||
return destShape;
|
||
}
|
||
}
|
||
|
||
class ShapeUtils {
|
||
static _randomPointUnitArcCircle(arc, out, rand = null) {
|
||
var angle;
|
||
if (rand)
|
||
angle = rand.getFloat() * arc;
|
||
else
|
||
angle = Math.random() * arc;
|
||
out.x = Math.cos(angle);
|
||
out.y = Math.sin(angle);
|
||
}
|
||
static _randomPointInsideUnitArcCircle(arc, out, rand = null) {
|
||
ShapeUtils._randomPointUnitArcCircle(arc, out, rand);
|
||
var range;
|
||
if (rand)
|
||
range = Math.pow(rand.getFloat(), 1.0 / 2.0);
|
||
else
|
||
range = Math.pow(Math.random(), 1.0 / 2.0);
|
||
out.x = out.x * range;
|
||
out.y = out.y * range;
|
||
}
|
||
static _randomPointUnitCircle(out, rand = null) {
|
||
var angle;
|
||
if (rand)
|
||
angle = rand.getFloat() * Math.PI * 2;
|
||
else
|
||
angle = Math.random() * Math.PI * 2;
|
||
out.x = Math.cos(angle);
|
||
out.y = Math.sin(angle);
|
||
}
|
||
static _randomPointInsideUnitCircle(out, rand = null) {
|
||
ShapeUtils._randomPointUnitCircle(out);
|
||
var range;
|
||
if (rand)
|
||
range = Math.pow(rand.getFloat(), 1.0 / 2.0);
|
||
else
|
||
range = Math.pow(Math.random(), 1.0 / 2.0);
|
||
out.x = out.x * range;
|
||
out.y = out.y * range;
|
||
}
|
||
static _randomPointUnitSphere(out, rand = null) {
|
||
var z;
|
||
var a;
|
||
if (rand) {
|
||
z = out.z = rand.getFloat() * 2 - 1.0;
|
||
a = rand.getFloat() * Math.PI * 2;
|
||
}
|
||
else {
|
||
z = out.z = Math.random() * 2 - 1.0;
|
||
a = Math.random() * Math.PI * 2;
|
||
}
|
||
var r = Math.sqrt(1.0 - z * z);
|
||
out.x = r * Math.cos(a);
|
||
out.y = r * Math.sin(a);
|
||
}
|
||
static _randomPointInsideUnitSphere(out, rand = null) {
|
||
ShapeUtils._randomPointUnitSphere(out);
|
||
var range;
|
||
if (rand)
|
||
range = Math.pow(rand.getFloat(), 1.0 / 3.0);
|
||
else
|
||
range = Math.pow(Math.random(), 1.0 / 3.0);
|
||
out.x = out.x * range;
|
||
out.y = out.y * range;
|
||
out.z = out.z * range;
|
||
}
|
||
static _randomPointInsideHalfUnitBox(out, rand = null) {
|
||
if (rand) {
|
||
out.x = (rand.getFloat() - 0.5);
|
||
out.y = (rand.getFloat() - 0.5);
|
||
out.z = (rand.getFloat() - 0.5);
|
||
}
|
||
else {
|
||
out.x = (Math.random() - 0.5);
|
||
out.y = (Math.random() - 0.5);
|
||
out.z = (Math.random() - 0.5);
|
||
}
|
||
}
|
||
constructor() {
|
||
}
|
||
}
|
||
|
||
class BoxShape extends BaseShape {
|
||
constructor() {
|
||
super();
|
||
this.shapeType = exports.ParticleSystemShapeType.Box;
|
||
this.x = 1.0;
|
||
this.y = 1.0;
|
||
this.z = 1.0;
|
||
}
|
||
_getShapeBoundBox(boundBox) {
|
||
var min = boundBox.min;
|
||
min.x = -this.x * 0.5;
|
||
min.y = -this.y * 0.5;
|
||
min.z = -this.z * 0.5;
|
||
var max = boundBox.max;
|
||
max.x = this.x * 0.5;
|
||
max.y = this.y * 0.5;
|
||
max.z = this.z * 0.5;
|
||
}
|
||
_getSpeedBoundBox(boundBox) {
|
||
var min = boundBox.min;
|
||
min.x = 0.0;
|
||
min.y = 0.0;
|
||
min.z = 0.0;
|
||
var max = boundBox.max;
|
||
max.x = 0.0;
|
||
max.y = 1.0;
|
||
max.z = 0.0;
|
||
}
|
||
generatePositionAndDirection(position, direction, rand = null, randomSeeds = null) {
|
||
if (rand) {
|
||
rand.seed = randomSeeds[16];
|
||
ShapeUtils._randomPointInsideHalfUnitBox(position, rand);
|
||
randomSeeds[16] = rand.seed;
|
||
}
|
||
else {
|
||
ShapeUtils._randomPointInsideHalfUnitBox(position);
|
||
}
|
||
position.x = this.x * position.x;
|
||
position.y = this.y * position.y;
|
||
position.z = this.z * position.z;
|
||
if (this.randomDirection) {
|
||
if (rand) {
|
||
rand.seed = randomSeeds[17];
|
||
ShapeUtils._randomPointUnitSphere(direction, rand);
|
||
randomSeeds[17] = rand.seed;
|
||
}
|
||
else {
|
||
ShapeUtils._randomPointUnitSphere(direction);
|
||
}
|
||
}
|
||
else {
|
||
direction.x = 0.0;
|
||
direction.y = 0.0;
|
||
direction.z = 1.0;
|
||
}
|
||
}
|
||
cloneTo(destObject) {
|
||
super.cloneTo(destObject);
|
||
var destShape = destObject;
|
||
destShape.x = this.x;
|
||
destShape.y = this.y;
|
||
destShape.z = this.z;
|
||
destShape.randomDirection = this.randomDirection;
|
||
}
|
||
clone() {
|
||
var destShape = new BoxShape();
|
||
this.cloneTo(destShape);
|
||
return destShape;
|
||
}
|
||
}
|
||
|
||
class CircleShape extends BaseShape {
|
||
constructor() {
|
||
super();
|
||
this.shapeType = exports.ParticleSystemShapeType.Circle;
|
||
this.radius = 1.0;
|
||
this.arc = 360.0 / 180.0 * Math.PI;
|
||
this.emitFromEdge = false;
|
||
}
|
||
_getShapeBoundBox(boundBox) {
|
||
var min = boundBox.min;
|
||
min.x = min.z = -this.radius;
|
||
min.y = 0;
|
||
var max = boundBox.max;
|
||
max.x = max.z = this.radius;
|
||
max.y = 0;
|
||
}
|
||
_getSpeedBoundBox(boundBox) {
|
||
var min = boundBox.min;
|
||
min.x = min.y = -1;
|
||
min.z = 0;
|
||
var max = boundBox.max;
|
||
max.x = max.y = 1;
|
||
max.z = 0;
|
||
}
|
||
generatePositionAndDirection(position, direction, rand = null, randomSeeds = null) {
|
||
var positionPoint = CircleShape._tempPositionPoint;
|
||
if (rand) {
|
||
rand.seed = randomSeeds[16];
|
||
if (this.emitFromEdge)
|
||
ShapeUtils._randomPointUnitArcCircle(this.arc, CircleShape._tempPositionPoint, rand);
|
||
else
|
||
ShapeUtils._randomPointInsideUnitArcCircle(this.arc, CircleShape._tempPositionPoint, rand);
|
||
randomSeeds[16] = rand.seed;
|
||
}
|
||
else {
|
||
if (this.emitFromEdge)
|
||
ShapeUtils._randomPointUnitArcCircle(this.arc, CircleShape._tempPositionPoint);
|
||
else
|
||
ShapeUtils._randomPointInsideUnitArcCircle(this.arc, CircleShape._tempPositionPoint);
|
||
}
|
||
position.x = -positionPoint.x;
|
||
position.y = positionPoint.y;
|
||
position.z = 0;
|
||
Vector3.scale(position, this.radius, position);
|
||
if (this.randomDirection) {
|
||
if (rand) {
|
||
rand.seed = randomSeeds[17];
|
||
ShapeUtils._randomPointUnitSphere(direction, rand);
|
||
randomSeeds[17] = rand.seed;
|
||
}
|
||
else {
|
||
ShapeUtils._randomPointUnitSphere(direction);
|
||
}
|
||
}
|
||
else {
|
||
position.cloneTo(direction);
|
||
}
|
||
}
|
||
cloneTo(destObject) {
|
||
super.cloneTo(destObject);
|
||
var destShape = destObject;
|
||
destShape.radius = this.radius;
|
||
destShape.arc = this.arc;
|
||
destShape.emitFromEdge = this.emitFromEdge;
|
||
destShape.randomDirection = this.randomDirection;
|
||
}
|
||
clone() {
|
||
var destShape = new CircleShape();
|
||
this.cloneTo(destShape);
|
||
return destShape;
|
||
}
|
||
}
|
||
CircleShape._tempPositionPoint = new Vector2();
|
||
|
||
class ConeShape extends BaseShape {
|
||
constructor() {
|
||
super();
|
||
this.shapeType = exports.ParticleSystemShapeType.Cone;
|
||
this.angle = 25.0 / 180.0 * Math.PI;
|
||
this.radius = 1.0;
|
||
this.length = 5.0;
|
||
this.emitType = 0;
|
||
}
|
||
_getShapeBoundBox(boundBox) {
|
||
const coneRadius2 = this.radius + this.length * Math.sin(this.angle);
|
||
const coneLength = this.length * Math.cos(this.angle);
|
||
var min = boundBox.min;
|
||
min.x = min.y = -coneRadius2;
|
||
min.z = 0;
|
||
var max = boundBox.max;
|
||
max.x = max.y = coneRadius2;
|
||
max.z = coneLength;
|
||
}
|
||
_getSpeedBoundBox(boundBox) {
|
||
const sinA = Math.sin(this.angle);
|
||
var min = boundBox.min;
|
||
min.x = min.y = -sinA;
|
||
min.z = 0;
|
||
var max = boundBox.max;
|
||
max.x = max.y = sinA;
|
||
max.z = 1;
|
||
}
|
||
generatePositionAndDirection(position, direction, rand = null, randomSeeds = null) {
|
||
var positionPointE = ConeShape._tempPositionPoint;
|
||
var positionX;
|
||
var positionY;
|
||
var directionPointE;
|
||
var dirCosA = Math.cos(this.angle);
|
||
var dirSinA = Math.sin(this.angle);
|
||
switch (this.emitType) {
|
||
case 0:
|
||
if (rand) {
|
||
rand.seed = randomSeeds[16];
|
||
ShapeUtils._randomPointInsideUnitCircle(ConeShape._tempPositionPoint, rand);
|
||
randomSeeds[16] = rand.seed;
|
||
}
|
||
else {
|
||
ShapeUtils._randomPointInsideUnitCircle(ConeShape._tempPositionPoint);
|
||
}
|
||
positionX = positionPointE.x;
|
||
positionY = positionPointE.y;
|
||
position.x = positionX * this.radius;
|
||
position.y = positionY * this.radius;
|
||
position.z = 0;
|
||
if (this.randomDirection) {
|
||
if (rand) {
|
||
rand.seed = randomSeeds[17];
|
||
ShapeUtils._randomPointInsideUnitCircle(ConeShape._tempDirectionPoint, rand);
|
||
randomSeeds[17] = rand.seed;
|
||
}
|
||
else {
|
||
ShapeUtils._randomPointInsideUnitCircle(ConeShape._tempDirectionPoint);
|
||
}
|
||
directionPointE = ConeShape._tempDirectionPoint;
|
||
direction.x = directionPointE.x * dirSinA;
|
||
direction.y = directionPointE.y * dirSinA;
|
||
}
|
||
else {
|
||
direction.x = positionX * dirSinA;
|
||
direction.y = positionY * dirSinA;
|
||
}
|
||
direction.z = dirCosA;
|
||
break;
|
||
case 1:
|
||
if (rand) {
|
||
rand.seed = randomSeeds[16];
|
||
ShapeUtils._randomPointUnitCircle(ConeShape._tempPositionPoint, rand);
|
||
randomSeeds[16] = rand.seed;
|
||
}
|
||
else {
|
||
ShapeUtils._randomPointUnitCircle(ConeShape._tempPositionPoint);
|
||
}
|
||
positionX = positionPointE.x;
|
||
positionY = positionPointE.y;
|
||
position.x = positionX * this.radius;
|
||
position.y = positionY * this.radius;
|
||
position.z = 0;
|
||
if (this.randomDirection) {
|
||
if (rand) {
|
||
rand.seed = randomSeeds[17];
|
||
ShapeUtils._randomPointInsideUnitCircle(ConeShape._tempDirectionPoint, rand);
|
||
randomSeeds[17] = rand.seed;
|
||
}
|
||
else {
|
||
ShapeUtils._randomPointInsideUnitCircle(ConeShape._tempDirectionPoint);
|
||
}
|
||
directionPointE = ConeShape._tempDirectionPoint;
|
||
direction.x = directionPointE.x * dirSinA;
|
||
direction.y = directionPointE.y * dirSinA;
|
||
}
|
||
else {
|
||
direction.x = positionX * dirSinA;
|
||
direction.y = positionY * dirSinA;
|
||
}
|
||
direction.z = dirCosA;
|
||
break;
|
||
case 2:
|
||
if (rand) {
|
||
rand.seed = randomSeeds[16];
|
||
ShapeUtils._randomPointInsideUnitCircle(ConeShape._tempPositionPoint, rand);
|
||
}
|
||
else {
|
||
ShapeUtils._randomPointInsideUnitCircle(ConeShape._tempPositionPoint);
|
||
}
|
||
positionX = positionPointE.x;
|
||
positionY = positionPointE.y;
|
||
position.x = positionX * this.radius;
|
||
position.y = positionY * this.radius;
|
||
position.z = 0;
|
||
direction.x = positionX * dirSinA;
|
||
direction.y = positionY * dirSinA;
|
||
direction.z = dirCosA;
|
||
Vector3.normalize(direction, direction);
|
||
if (rand) {
|
||
Vector3.scale(direction, this.length * rand.getFloat(), direction);
|
||
randomSeeds[16] = rand.seed;
|
||
}
|
||
else {
|
||
Vector3.scale(direction, this.length * Math.random(), direction);
|
||
}
|
||
Vector3.add(position, direction, position);
|
||
if (this.randomDirection) {
|
||
if (rand) {
|
||
rand.seed = randomSeeds[17];
|
||
ShapeUtils._randomPointUnitSphere(direction, rand);
|
||
randomSeeds[17] = rand.seed;
|
||
}
|
||
else {
|
||
ShapeUtils._randomPointUnitSphere(direction);
|
||
}
|
||
}
|
||
break;
|
||
case 3:
|
||
if (rand) {
|
||
rand.seed = randomSeeds[16];
|
||
ShapeUtils._randomPointUnitCircle(ConeShape._tempPositionPoint, rand);
|
||
}
|
||
else {
|
||
ShapeUtils._randomPointUnitCircle(ConeShape._tempPositionPoint);
|
||
}
|
||
positionX = positionPointE.x;
|
||
positionY = positionPointE.y;
|
||
position.x = positionX * this.radius;
|
||
position.y = positionY * this.radius;
|
||
position.z = 0;
|
||
direction.x = positionX * dirSinA;
|
||
direction.y = positionY * dirSinA;
|
||
direction.z = dirCosA;
|
||
Vector3.normalize(direction, direction);
|
||
if (rand) {
|
||
Vector3.scale(direction, this.length * rand.getFloat(), direction);
|
||
randomSeeds[16] = rand.seed;
|
||
}
|
||
else {
|
||
Vector3.scale(direction, this.length * Math.random(), direction);
|
||
}
|
||
Vector3.add(position, direction, position);
|
||
if (this.randomDirection) {
|
||
if (rand) {
|
||
rand.seed = randomSeeds[17];
|
||
ShapeUtils._randomPointUnitSphere(direction, rand);
|
||
randomSeeds[17] = rand.seed;
|
||
}
|
||
else {
|
||
ShapeUtils._randomPointUnitSphere(direction);
|
||
}
|
||
}
|
||
break;
|
||
default:
|
||
throw new Error("ConeShape:emitType is invalid.");
|
||
}
|
||
}
|
||
cloneTo(destObject) {
|
||
super.cloneTo(destObject);
|
||
var destShape = destObject;
|
||
destShape.angle = this.angle;
|
||
destShape.radius = this.radius;
|
||
destShape.length = this.length;
|
||
destShape.emitType = this.emitType;
|
||
destShape.randomDirection = this.randomDirection;
|
||
}
|
||
clone() {
|
||
var destShape = new ConeShape();
|
||
this.cloneTo(destShape);
|
||
return destShape;
|
||
}
|
||
}
|
||
ConeShape._tempPositionPoint = new Vector2();
|
||
ConeShape._tempDirectionPoint = new Vector2();
|
||
|
||
class HemisphereShape extends BaseShape {
|
||
constructor() {
|
||
super();
|
||
this.shapeType = exports.ParticleSystemShapeType.Hemisphere;
|
||
this.radius = 1.0;
|
||
this.emitFromShell = false;
|
||
}
|
||
_getShapeBoundBox(boundBox) {
|
||
var min = boundBox.min;
|
||
min.x = min.y = min.z = -this.radius;
|
||
var max = boundBox.max;
|
||
max.x = max.y = this.radius;
|
||
max.z = 0;
|
||
}
|
||
_getSpeedBoundBox(boundBox) {
|
||
var min = boundBox.min;
|
||
min.x = min.y = -1;
|
||
min.z = 0;
|
||
var max = boundBox.max;
|
||
max.x = max.y = max.z = 1;
|
||
}
|
||
generatePositionAndDirection(position, direction, rand = null, randomSeeds = null) {
|
||
if (rand) {
|
||
rand.seed = randomSeeds[16];
|
||
if (this.emitFromShell)
|
||
ShapeUtils._randomPointUnitSphere(position, rand);
|
||
else
|
||
ShapeUtils._randomPointInsideUnitSphere(position, rand);
|
||
randomSeeds[16] = rand.seed;
|
||
}
|
||
else {
|
||
if (this.emitFromShell)
|
||
ShapeUtils._randomPointUnitSphere(position);
|
||
else
|
||
ShapeUtils._randomPointInsideUnitSphere(position);
|
||
}
|
||
Vector3.scale(position, this.radius, position);
|
||
var z = position.z;
|
||
(z < 0.0) && (position.z = z * -1.0);
|
||
if (this.randomDirection) {
|
||
if (rand) {
|
||
rand.seed = randomSeeds[17];
|
||
ShapeUtils._randomPointUnitSphere(direction, rand);
|
||
randomSeeds[17] = rand.seed;
|
||
}
|
||
else {
|
||
ShapeUtils._randomPointUnitSphere(direction);
|
||
}
|
||
}
|
||
else {
|
||
position.cloneTo(direction);
|
||
}
|
||
}
|
||
cloneTo(destObject) {
|
||
super.cloneTo(destObject);
|
||
var destShape = destObject;
|
||
destShape.radius = this.radius;
|
||
destShape.emitFromShell = this.emitFromShell;
|
||
destShape.randomDirection = this.randomDirection;
|
||
}
|
||
clone() {
|
||
var destShape = new HemisphereShape();
|
||
this.cloneTo(destShape);
|
||
return destShape;
|
||
}
|
||
}
|
||
|
||
class SphereShape extends BaseShape {
|
||
constructor() {
|
||
super();
|
||
this.shapeType = exports.ParticleSystemShapeType.Sphere;
|
||
this.radius = 1.0;
|
||
this.emitFromShell = false;
|
||
}
|
||
_getShapeBoundBox(boundBox) {
|
||
var min = boundBox.min;
|
||
min.x = min.y = min.z = -this.radius;
|
||
var max = boundBox.max;
|
||
max.x = max.y = max.z = this.radius;
|
||
}
|
||
_getSpeedBoundBox(boundBox) {
|
||
var min = boundBox.min;
|
||
min.x = min.y = min.z = -1;
|
||
var max = boundBox.max;
|
||
max.x = max.y = max.z = 1;
|
||
}
|
||
generatePositionAndDirection(position, direction, rand = null, randomSeeds = null) {
|
||
if (rand) {
|
||
rand.seed = randomSeeds[16];
|
||
if (this.emitFromShell)
|
||
ShapeUtils._randomPointUnitSphere(position, rand);
|
||
else
|
||
ShapeUtils._randomPointInsideUnitSphere(position, rand);
|
||
randomSeeds[16] = rand.seed;
|
||
}
|
||
else {
|
||
if (this.emitFromShell)
|
||
ShapeUtils._randomPointUnitSphere(position);
|
||
else
|
||
ShapeUtils._randomPointInsideUnitSphere(position);
|
||
}
|
||
Vector3.scale(position, this.radius, position);
|
||
if (this.randomDirection) {
|
||
if (rand) {
|
||
rand.seed = randomSeeds[17];
|
||
ShapeUtils._randomPointUnitSphere(direction, rand);
|
||
randomSeeds[17] = rand.seed;
|
||
}
|
||
else {
|
||
ShapeUtils._randomPointUnitSphere(direction);
|
||
}
|
||
}
|
||
else {
|
||
position.cloneTo(direction);
|
||
}
|
||
}
|
||
cloneTo(destObject) {
|
||
super.cloneTo(destObject);
|
||
var destShape = destObject;
|
||
destShape.radius = this.radius;
|
||
destShape.emitFromShell = this.emitFromShell;
|
||
destShape.randomDirection = this.randomDirection;
|
||
}
|
||
clone() {
|
||
var destShape = new SphereShape();
|
||
this.cloneTo(destShape);
|
||
return destShape;
|
||
}
|
||
}
|
||
|
||
class SizeOverLifetime {
|
||
constructor(size) {
|
||
this._size = size;
|
||
}
|
||
get size() {
|
||
return this._size;
|
||
}
|
||
cloneTo(destObject) {
|
||
var destSizeOverLifetime = destObject;
|
||
this._size.cloneTo(destSizeOverLifetime._size);
|
||
destSizeOverLifetime.enable = this.enable;
|
||
}
|
||
clone() {
|
||
var destSize;
|
||
switch (this._size.type) {
|
||
case 0:
|
||
if (this._size.separateAxes)
|
||
destSize = GradientSize.createByGradientSeparate(this._size.gradientX.clone(), this._size.gradientY.clone(), this._size.gradientZ.clone());
|
||
else
|
||
destSize = GradientSize.createByGradient(this._size.gradient.clone());
|
||
break;
|
||
case 1:
|
||
if (this._size.separateAxes)
|
||
destSize = GradientSize.createByRandomTwoConstantSeparate(this._size.constantMinSeparate.clone(), this._size.constantMaxSeparate.clone());
|
||
else
|
||
destSize = GradientSize.createByRandomTwoConstant(this._size.constantMin, this._size.constantMax);
|
||
break;
|
||
case 2:
|
||
if (this._size.separateAxes)
|
||
destSize = GradientSize.createByRandomTwoGradientSeparate(this._size.gradientXMin.clone(), this._size.gradientYMin.clone(), this._size.gradientZMin.clone(), this._size.gradientXMax.clone(), this._size.gradientYMax.clone(), this._size.gradientZMax.clone());
|
||
else
|
||
destSize = GradientSize.createByRandomTwoGradient(this._size.gradientMin.clone(), this._size.gradientMax.clone());
|
||
break;
|
||
}
|
||
var destSizeOverLifetime = new SizeOverLifetime(destSize);
|
||
destSizeOverLifetime.enable = this.enable;
|
||
return destSizeOverLifetime;
|
||
}
|
||
}
|
||
|
||
class StartFrame {
|
||
constructor() {
|
||
this._type = 0;
|
||
this._constant = 0;
|
||
this._constantMin = 0;
|
||
this._constantMax = 0;
|
||
}
|
||
static createByConstant(constant = 0) {
|
||
var rotationOverLifetime = new StartFrame();
|
||
rotationOverLifetime._type = 0;
|
||
rotationOverLifetime._constant = constant;
|
||
return rotationOverLifetime;
|
||
}
|
||
static createByRandomTwoConstant(constantMin = 0, constantMax = 0) {
|
||
var rotationOverLifetime = new StartFrame();
|
||
rotationOverLifetime._type = 1;
|
||
rotationOverLifetime._constantMin = constantMin;
|
||
rotationOverLifetime._constantMax = constantMax;
|
||
return rotationOverLifetime;
|
||
}
|
||
get type() {
|
||
return this._type;
|
||
}
|
||
get constant() {
|
||
return this._constant;
|
||
}
|
||
get constantMin() {
|
||
return this._constantMin;
|
||
}
|
||
get constantMax() {
|
||
return this._constantMax;
|
||
}
|
||
cloneTo(destObject) {
|
||
var destStartFrame = destObject;
|
||
destStartFrame._type = this._type;
|
||
destStartFrame._constant = this._constant;
|
||
destStartFrame._constantMin = this._constantMin;
|
||
destStartFrame._constantMax = this._constantMax;
|
||
}
|
||
clone() {
|
||
var destStartFrame = new StartFrame();
|
||
this.cloneTo(destStartFrame);
|
||
return destStartFrame;
|
||
}
|
||
}
|
||
|
||
class TextureSheetAnimation {
|
||
constructor(frame, startFrame) {
|
||
this.type = 0;
|
||
this.randomRow = false;
|
||
this.rowIndex = 0;
|
||
this.cycles = 0;
|
||
this.enableUVChannels = 0;
|
||
this.enable = false;
|
||
this.tiles = new Vector2(1, 1);
|
||
this.type = 0;
|
||
this.randomRow = true;
|
||
this.rowIndex = 0;
|
||
this.cycles = 1;
|
||
this.enableUVChannels = 1;
|
||
this._frame = frame;
|
||
this._startFrame = startFrame;
|
||
}
|
||
get frame() {
|
||
return this._frame;
|
||
}
|
||
get startFrame() {
|
||
return this._startFrame;
|
||
}
|
||
cloneTo(destObject) {
|
||
var destTextureSheetAnimation = destObject;
|
||
this.tiles.cloneTo(destTextureSheetAnimation.tiles);
|
||
destTextureSheetAnimation.type = this.type;
|
||
destTextureSheetAnimation.randomRow = this.randomRow;
|
||
destTextureSheetAnimation.rowIndex = this.rowIndex;
|
||
destTextureSheetAnimation.cycles = this.cycles;
|
||
destTextureSheetAnimation.enableUVChannels = this.enableUVChannels;
|
||
destTextureSheetAnimation.enable = this.enable;
|
||
this._frame.cloneTo(destTextureSheetAnimation._frame);
|
||
this._startFrame.cloneTo(destTextureSheetAnimation._startFrame);
|
||
}
|
||
clone() {
|
||
var destFrame;
|
||
switch (this._frame.type) {
|
||
case 0:
|
||
destFrame = FrameOverTime.createByConstant(this._frame.constant);
|
||
break;
|
||
case 1:
|
||
destFrame = FrameOverTime.createByOverTime(this._frame.frameOverTimeData.clone());
|
||
break;
|
||
case 2:
|
||
destFrame = FrameOverTime.createByRandomTwoConstant(this._frame.constantMin, this._frame.constantMax);
|
||
break;
|
||
case 3:
|
||
destFrame = FrameOverTime.createByRandomTwoOverTime(this._frame.frameOverTimeDataMin.clone(), this._frame.frameOverTimeDataMax.clone());
|
||
break;
|
||
}
|
||
var destStartFrame;
|
||
switch (this._startFrame.type) {
|
||
case 0:
|
||
destStartFrame = StartFrame.createByConstant(this._startFrame.constant);
|
||
break;
|
||
case 1:
|
||
destStartFrame = StartFrame.createByRandomTwoConstant(this._startFrame.constantMin, this._startFrame.constantMax);
|
||
break;
|
||
}
|
||
var destTextureSheetAnimation = new TextureSheetAnimation(destFrame, destStartFrame);
|
||
this.cloneTo(destTextureSheetAnimation);
|
||
return destTextureSheetAnimation;
|
||
}
|
||
}
|
||
|
||
class VelocityOverLifetime {
|
||
constructor(velocity) {
|
||
this.enable = false;
|
||
this.space = 0;
|
||
this._velocity = velocity;
|
||
}
|
||
get velocity() {
|
||
return this._velocity;
|
||
}
|
||
cloneTo(destObject) {
|
||
var destVelocityOverLifetime = destObject;
|
||
this._velocity.cloneTo(destVelocityOverLifetime._velocity);
|
||
destVelocityOverLifetime.enable = this.enable;
|
||
destVelocityOverLifetime.space = this.space;
|
||
}
|
||
clone() {
|
||
var destVelocity;
|
||
switch (this._velocity.type) {
|
||
case 0:
|
||
destVelocity = GradientVelocity.createByConstant(this._velocity.constant.clone());
|
||
break;
|
||
case 1:
|
||
destVelocity = GradientVelocity.createByGradient(this._velocity.gradientX.clone(), this._velocity.gradientY.clone(), this._velocity.gradientZ.clone());
|
||
break;
|
||
case 2:
|
||
destVelocity = GradientVelocity.createByRandomTwoConstant(this._velocity.constantMin.clone(), this._velocity.constantMax.clone());
|
||
break;
|
||
case 3:
|
||
destVelocity = GradientVelocity.createByRandomTwoGradient(this._velocity.gradientXMin.clone(), this._velocity.gradientXMax.clone(), this._velocity.gradientYMin.clone(), this._velocity.gradientYMax.clone(), this._velocity.gradientZMin.clone(), this._velocity.gradientZMax.clone());
|
||
break;
|
||
}
|
||
var destVelocityOverLifetime = new VelocityOverLifetime(destVelocity);
|
||
destVelocityOverLifetime.enable = this.enable;
|
||
destVelocityOverLifetime.space = this.space;
|
||
return destVelocityOverLifetime;
|
||
}
|
||
}
|
||
|
||
class ShuriKenParticle3DShaderDeclaration {
|
||
}
|
||
ShuriKenParticle3DShaderDeclaration.WORLDPOSITION = Shader3D.propertyNameToID("u_WorldPosition");
|
||
ShuriKenParticle3DShaderDeclaration.WORLDROTATION = Shader3D.propertyNameToID("u_WorldRotation");
|
||
ShuriKenParticle3DShaderDeclaration.POSITIONSCALE = Shader3D.propertyNameToID("u_PositionScale");
|
||
ShuriKenParticle3DShaderDeclaration.SIZESCALE = Shader3D.propertyNameToID("u_SizeScale");
|
||
ShuriKenParticle3DShaderDeclaration.SCALINGMODE = Shader3D.propertyNameToID("u_ScalingMode");
|
||
ShuriKenParticle3DShaderDeclaration.GRAVITY = Shader3D.propertyNameToID("u_Gravity");
|
||
ShuriKenParticle3DShaderDeclaration.THREEDSTARTROTATION = Shader3D.propertyNameToID("u_ThreeDStartRotation");
|
||
ShuriKenParticle3DShaderDeclaration.STRETCHEDBILLBOARDLENGTHSCALE = Shader3D.propertyNameToID("u_StretchedBillboardLengthScale");
|
||
ShuriKenParticle3DShaderDeclaration.STRETCHEDBILLBOARDSPEEDSCALE = Shader3D.propertyNameToID("u_StretchedBillboardSpeedScale");
|
||
ShuriKenParticle3DShaderDeclaration.SIMULATIONSPACE = Shader3D.propertyNameToID("u_SimulationSpace");
|
||
ShuriKenParticle3DShaderDeclaration.CURRENTTIME = Shader3D.propertyNameToID("u_CurrentTime");
|
||
ShuriKenParticle3DShaderDeclaration.VOLVELOCITYCONST = Shader3D.propertyNameToID("u_VOLVelocityConst");
|
||
ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTX = Shader3D.propertyNameToID("u_VOLVelocityGradientX");
|
||
ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTY = Shader3D.propertyNameToID("u_VOLVelocityGradientY");
|
||
ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTZ = Shader3D.propertyNameToID("u_VOLVelocityGradientZ");
|
||
ShuriKenParticle3DShaderDeclaration.VOLVELOCITYCONSTMAX = Shader3D.propertyNameToID("u_VOLVelocityConstMax");
|
||
ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTXMAX = Shader3D.propertyNameToID("u_VOLVelocityGradientMaxX");
|
||
ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTYMAX = Shader3D.propertyNameToID("u_VOLVelocityGradientMaxY");
|
||
ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTZMAX = Shader3D.propertyNameToID("u_VOLVelocityGradientMaxZ");
|
||
ShuriKenParticle3DShaderDeclaration.VOLSPACETYPE = Shader3D.propertyNameToID("u_VOLSpaceType");
|
||
ShuriKenParticle3DShaderDeclaration.COLOROVERLIFEGRADIENTALPHAS = Shader3D.propertyNameToID("u_ColorOverLifeGradientAlphas");
|
||
ShuriKenParticle3DShaderDeclaration.COLOROVERLIFEGRADIENTCOLORS = Shader3D.propertyNameToID("u_ColorOverLifeGradientColors");
|
||
ShuriKenParticle3DShaderDeclaration.MAXCOLOROVERLIFEGRADIENTALPHAS = Shader3D.propertyNameToID("u_MaxColorOverLifeGradientAlphas");
|
||
ShuriKenParticle3DShaderDeclaration.MAXCOLOROVERLIFEGRADIENTCOLORS = Shader3D.propertyNameToID("u_MaxColorOverLifeGradientColors");
|
||
ShuriKenParticle3DShaderDeclaration.SOLSIZEGRADIENT = Shader3D.propertyNameToID("u_SOLSizeGradient");
|
||
ShuriKenParticle3DShaderDeclaration.SOLSIZEGRADIENTX = Shader3D.propertyNameToID("u_SOLSizeGradientX");
|
||
ShuriKenParticle3DShaderDeclaration.SOLSIZEGRADIENTY = Shader3D.propertyNameToID("u_SOLSizeGradientY");
|
||
ShuriKenParticle3DShaderDeclaration.SOLSizeGradientZ = Shader3D.propertyNameToID("u_SOLSizeGradientZ");
|
||
ShuriKenParticle3DShaderDeclaration.SOLSizeGradientMax = Shader3D.propertyNameToID("u_SOLSizeGradientMax");
|
||
ShuriKenParticle3DShaderDeclaration.SOLSIZEGRADIENTXMAX = Shader3D.propertyNameToID("u_SOLSizeGradientMaxX");
|
||
ShuriKenParticle3DShaderDeclaration.SOLSIZEGRADIENTYMAX = Shader3D.propertyNameToID("u_SOLSizeGradientMaxY");
|
||
ShuriKenParticle3DShaderDeclaration.SOLSizeGradientZMAX = Shader3D.propertyNameToID("u_SOLSizeGradientMaxZ");
|
||
ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYCONST = Shader3D.propertyNameToID("u_ROLAngularVelocityConst");
|
||
ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYCONSTSEPRARATE = Shader3D.propertyNameToID("u_ROLAngularVelocityConstSeprarate");
|
||
ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENT = Shader3D.propertyNameToID("u_ROLAngularVelocityGradient");
|
||
ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTX = Shader3D.propertyNameToID("u_ROLAngularVelocityGradientX");
|
||
ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTY = Shader3D.propertyNameToID("u_ROLAngularVelocityGradientY");
|
||
ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTZ = Shader3D.propertyNameToID("u_ROLAngularVelocityGradientZ");
|
||
ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYCONSTMAX = Shader3D.propertyNameToID("u_ROLAngularVelocityConstMax");
|
||
ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYCONSTMAXSEPRARATE = Shader3D.propertyNameToID("u_ROLAngularVelocityConstMaxSeprarate");
|
||
ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTMAX = Shader3D.propertyNameToID("u_ROLAngularVelocityGradientMax");
|
||
ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTXMAX = Shader3D.propertyNameToID("u_ROLAngularVelocityGradientMaxX");
|
||
ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTYMAX = Shader3D.propertyNameToID("u_ROLAngularVelocityGradientMaxY");
|
||
ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTZMAX = Shader3D.propertyNameToID("u_ROLAngularVelocityGradientMaxZ");
|
||
ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTWMAX = Shader3D.propertyNameToID("u_ROLAngularVelocityGradientMaxW");
|
||
ShuriKenParticle3DShaderDeclaration.TEXTURESHEETANIMATIONCYCLES = Shader3D.propertyNameToID("u_TSACycles");
|
||
ShuriKenParticle3DShaderDeclaration.TEXTURESHEETANIMATIONSUBUVLENGTH = Shader3D.propertyNameToID("u_TSASubUVLength");
|
||
ShuriKenParticle3DShaderDeclaration.TEXTURESHEETANIMATIONGRADIENTUVS = Shader3D.propertyNameToID("u_TSAGradientUVs");
|
||
ShuriKenParticle3DShaderDeclaration.TEXTURESHEETANIMATIONGRADIENTMAXUVS = Shader3D.propertyNameToID("u_TSAMaxGradientUVs");
|
||
|
||
class ShurikenParticleMaterial extends Material {
|
||
constructor() {
|
||
super();
|
||
this.setShaderName("PARTICLESHURIKEN");
|
||
this._shaderValues.setVector(ShurikenParticleMaterial.TINTCOLOR, new Vector4(0.5, 0.5, 0.5, 0.5));
|
||
this._shaderValues.setVector(ShurikenParticleMaterial.TILINGOFFSET, new Vector4(1.0, 1.0, 0.0, 0.0));
|
||
this.renderMode = ShurikenParticleMaterial.RENDERMODE_ALPHABLENDED;
|
||
}
|
||
static __initDefine__() {
|
||
ShurikenParticleMaterial.SHADERDEFINE_DIFFUSEMAP = Shader3D.getDefineByName("DIFFUSEMAP");
|
||
ShurikenParticleMaterial.SHADERDEFINE_TINTCOLOR = Shader3D.getDefineByName("TINTCOLOR");
|
||
ShurikenParticleMaterial.SHADERDEFINE_ADDTIVEFOG = Shader3D.getDefineByName("ADDTIVEFOG");
|
||
}
|
||
get _TintColor() {
|
||
return this.color;
|
||
}
|
||
set _TintColor(value) {
|
||
this.color = value;
|
||
}
|
||
get _TintColorR() {
|
||
return this.color.x;
|
||
}
|
||
set _TintColorR(value) {
|
||
this.color.x = value;
|
||
}
|
||
get _TintColorG() {
|
||
return this.color.y;
|
||
}
|
||
set _TintColorG(value) {
|
||
this.color.y = value;
|
||
}
|
||
get _TintColorB() {
|
||
return this.color.z;
|
||
}
|
||
set _TintColorB(value) {
|
||
this.color.z = value;
|
||
}
|
||
get _TintColorA() {
|
||
return this.color.w;
|
||
}
|
||
set _TintColorA(value) {
|
||
this.color.w = value;
|
||
}
|
||
get _MainTex_ST() {
|
||
return this._shaderValues.getVector(ShurikenParticleMaterial.TILINGOFFSET);
|
||
}
|
||
set _MainTex_ST(value) {
|
||
var tilOff = this._shaderValues.getVector(ShurikenParticleMaterial.TILINGOFFSET);
|
||
tilOff.setValue(value.x, value.y, value.z, value.w);
|
||
this.tilingOffset = tilOff;
|
||
}
|
||
get _MainTex_STX() {
|
||
return this._shaderValues.getVector(ShurikenParticleMaterial.TILINGOFFSET).x;
|
||
}
|
||
set _MainTex_STX(x) {
|
||
var tilOff = this._shaderValues.getVector(ShurikenParticleMaterial.TILINGOFFSET);
|
||
tilOff.x = x;
|
||
this.tilingOffset = tilOff;
|
||
}
|
||
get _MainTex_STY() {
|
||
return this._shaderValues.getVector(ShurikenParticleMaterial.TILINGOFFSET).y;
|
||
}
|
||
set _MainTex_STY(y) {
|
||
var tilOff = this._shaderValues.getVector(ShurikenParticleMaterial.TILINGOFFSET);
|
||
tilOff.y = y;
|
||
this.tilingOffset = tilOff;
|
||
}
|
||
get _MainTex_STZ() {
|
||
return this._shaderValues.getVector(ShurikenParticleMaterial.TILINGOFFSET).z;
|
||
}
|
||
set _MainTex_STZ(z) {
|
||
var tilOff = this._shaderValues.getVector(ShurikenParticleMaterial.TILINGOFFSET);
|
||
tilOff.z = z;
|
||
this.tilingOffset = tilOff;
|
||
}
|
||
get _MainTex_STW() {
|
||
return this._shaderValues.getVector(ShurikenParticleMaterial.TILINGOFFSET).w;
|
||
}
|
||
set _MainTex_STW(w) {
|
||
var tilOff = this._shaderValues.getVector(ShurikenParticleMaterial.TILINGOFFSET);
|
||
tilOff.w = w;
|
||
this.tilingOffset = tilOff;
|
||
}
|
||
set renderMode(value) {
|
||
switch (value) {
|
||
case ShurikenParticleMaterial.RENDERMODE_ADDTIVE:
|
||
this.renderQueue = Material.RENDERQUEUE_TRANSPARENT;
|
||
this.depthWrite = false;
|
||
this.cull = RenderState.CULL_NONE;
|
||
this.blend = RenderState.BLEND_ENABLE_ALL;
|
||
this.blendSrc = RenderState.BLENDPARAM_SRC_ALPHA;
|
||
this.blendDst = RenderState.BLENDPARAM_ONE;
|
||
this.alphaTest = false;
|
||
this._shaderValues.addDefine(ShurikenParticleMaterial.SHADERDEFINE_ADDTIVEFOG);
|
||
break;
|
||
case ShurikenParticleMaterial.RENDERMODE_ALPHABLENDED:
|
||
this.renderQueue = Material.RENDERQUEUE_TRANSPARENT;
|
||
this.depthWrite = false;
|
||
this.cull = RenderState.CULL_NONE;
|
||
this.blend = RenderState.BLEND_ENABLE_ALL;
|
||
this.blendSrc = RenderState.BLENDPARAM_SRC_ALPHA;
|
||
this.blendDst = RenderState.BLENDPARAM_ONE_MINUS_SRC_ALPHA;
|
||
this.alphaTest = false;
|
||
this._shaderValues.removeDefine(ShurikenParticleMaterial.SHADERDEFINE_ADDTIVEFOG);
|
||
break;
|
||
default:
|
||
throw new Error("ShurikenParticleMaterial : renderMode value error.");
|
||
}
|
||
}
|
||
get colorR() {
|
||
return this._TintColorR;
|
||
}
|
||
set colorR(value) {
|
||
this._TintColorR = value;
|
||
}
|
||
get colorG() {
|
||
return this._TintColorG;
|
||
}
|
||
set colorG(value) {
|
||
this._TintColorG = value;
|
||
}
|
||
get colorB() {
|
||
return this._TintColorB;
|
||
}
|
||
set colorB(value) {
|
||
this._TintColorB = value;
|
||
}
|
||
get colorA() {
|
||
return this._TintColorA;
|
||
}
|
||
set colorA(value) {
|
||
this._TintColorA = value;
|
||
}
|
||
get color() {
|
||
return this._shaderValues.getVector(ShurikenParticleMaterial.TINTCOLOR);
|
||
}
|
||
set color(value) {
|
||
if (value)
|
||
this._shaderValues.addDefine(ShurikenParticleMaterial.SHADERDEFINE_TINTCOLOR);
|
||
else
|
||
this._shaderValues.removeDefine(ShurikenParticleMaterial.SHADERDEFINE_TINTCOLOR);
|
||
this._shaderValues.setVector(ShurikenParticleMaterial.TINTCOLOR, value);
|
||
}
|
||
get tilingOffsetX() {
|
||
return this._MainTex_STX;
|
||
}
|
||
set tilingOffsetX(x) {
|
||
this._MainTex_STX = x;
|
||
}
|
||
get tilingOffsetY() {
|
||
return this._MainTex_STY;
|
||
}
|
||
set tilingOffsetY(y) {
|
||
this._MainTex_STY = y;
|
||
}
|
||
get tilingOffsetZ() {
|
||
return this._MainTex_STZ;
|
||
}
|
||
set tilingOffsetZ(z) {
|
||
this._MainTex_STZ = z;
|
||
}
|
||
get tilingOffsetW() {
|
||
return this._MainTex_STW;
|
||
}
|
||
set tilingOffsetW(w) {
|
||
this._MainTex_STW = w;
|
||
}
|
||
get tilingOffset() {
|
||
return this._shaderValues.getVector(ShurikenParticleMaterial.TILINGOFFSET);
|
||
}
|
||
set tilingOffset(value) {
|
||
if (value) {
|
||
this._shaderValues.setVector(ShurikenParticleMaterial.TILINGOFFSET, value);
|
||
}
|
||
else {
|
||
this._shaderValues.getVector(ShurikenParticleMaterial.TILINGOFFSET).setValue(1.0, 1.0, 0.0, 0.0);
|
||
}
|
||
}
|
||
get texture() {
|
||
return this._shaderValues.getTexture(ShurikenParticleMaterial.DIFFUSETEXTURE);
|
||
}
|
||
set texture(value) {
|
||
if (value)
|
||
this._shaderValues.addDefine(ShurikenParticleMaterial.SHADERDEFINE_DIFFUSEMAP);
|
||
else
|
||
this._shaderValues.removeDefine(ShurikenParticleMaterial.SHADERDEFINE_DIFFUSEMAP);
|
||
this._shaderValues.setTexture(ShurikenParticleMaterial.DIFFUSETEXTURE, value);
|
||
}
|
||
clone() {
|
||
var dest = new ShurikenParticleMaterial();
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
}
|
||
ShurikenParticleMaterial.RENDERMODE_ALPHABLENDED = 0;
|
||
ShurikenParticleMaterial.RENDERMODE_ADDTIVE = 1;
|
||
ShurikenParticleMaterial.DIFFUSETEXTURE = Shader3D.propertyNameToID("u_texture");
|
||
ShurikenParticleMaterial.TINTCOLOR = Shader3D.propertyNameToID("u_Tintcolor");
|
||
ShurikenParticleMaterial.TILINGOFFSET = Shader3D.propertyNameToID("u_TilingOffset");
|
||
|
||
class Physics3DUtils {
|
||
constructor() {
|
||
}
|
||
static setColliderCollision(collider1, collider2, collsion) {
|
||
}
|
||
static getIColliderCollision(collider1, collider2) {
|
||
return false;
|
||
}
|
||
}
|
||
Physics3DUtils.COLLISIONFILTERGROUP_DEFAULTFILTER = 0x1;
|
||
Physics3DUtils.COLLISIONFILTERGROUP_STATICFILTER = 0x2;
|
||
Physics3DUtils.COLLISIONFILTERGROUP_KINEMATICFILTER = 0x4;
|
||
Physics3DUtils.COLLISIONFILTERGROUP_DEBRISFILTER = 0x8;
|
||
Physics3DUtils.COLLISIONFILTERGROUP_SENSORTRIGGER = 0x10;
|
||
Physics3DUtils.COLLISIONFILTERGROUP_CHARACTERFILTER = 0x20;
|
||
Physics3DUtils.COLLISIONFILTERGROUP_CUSTOMFILTER1 = 0x40;
|
||
Physics3DUtils.COLLISIONFILTERGROUP_CUSTOMFILTER2 = 0x80;
|
||
Physics3DUtils.COLLISIONFILTERGROUP_CUSTOMFILTER3 = 0x100;
|
||
Physics3DUtils.COLLISIONFILTERGROUP_CUSTOMFILTER4 = 0x200;
|
||
Physics3DUtils.COLLISIONFILTERGROUP_CUSTOMFILTER5 = 0x400;
|
||
Physics3DUtils.COLLISIONFILTERGROUP_CUSTOMFILTER6 = 0x800;
|
||
Physics3DUtils.COLLISIONFILTERGROUP_CUSTOMFILTER7 = 0x1000;
|
||
Physics3DUtils.COLLISIONFILTERGROUP_CUSTOMFILTER8 = 0x2000;
|
||
Physics3DUtils.COLLISIONFILTERGROUP_CUSTOMFILTER9 = 0x4000;
|
||
Physics3DUtils.COLLISIONFILTERGROUP_CUSTOMFILTER10 = 0x8000;
|
||
Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER = -1;
|
||
Physics3DUtils.gravity = new Vector3(0, -9.81, 0);
|
||
|
||
class ShurikenParticleRenderer extends BaseRender {
|
||
constructor(owner) {
|
||
super(owner);
|
||
this._finalGravity = new Vector3();
|
||
this._mesh = null;
|
||
this.stretchedBillboardCameraSpeedScale = 0;
|
||
this.stretchedBillboardSpeedScale = 0;
|
||
this.stretchedBillboardLengthScale = 2;
|
||
this.renderMode = 0;
|
||
this._supportOctree = false;
|
||
}
|
||
get renderMode() {
|
||
return this._renderMode;
|
||
}
|
||
set renderMode(value) {
|
||
if (this._renderMode !== value) {
|
||
var defineDatas = this._shaderValues;
|
||
switch (this._renderMode) {
|
||
case 0:
|
||
defineDatas.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_BILLBOARD);
|
||
break;
|
||
case 1:
|
||
defineDatas.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_STRETCHEDBILLBOARD);
|
||
break;
|
||
case 2:
|
||
defineDatas.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_HORIZONTALBILLBOARD);
|
||
break;
|
||
case 3:
|
||
defineDatas.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_VERTICALBILLBOARD);
|
||
break;
|
||
case 4:
|
||
defineDatas.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_MESH);
|
||
break;
|
||
}
|
||
this._renderMode = value;
|
||
switch (value) {
|
||
case 0:
|
||
defineDatas.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_BILLBOARD);
|
||
break;
|
||
case 1:
|
||
defineDatas.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_STRETCHEDBILLBOARD);
|
||
break;
|
||
case 2:
|
||
defineDatas.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_HORIZONTALBILLBOARD);
|
||
break;
|
||
case 3:
|
||
defineDatas.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_VERTICALBILLBOARD);
|
||
break;
|
||
case 4:
|
||
defineDatas.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_MESH);
|
||
break;
|
||
default:
|
||
throw new Error("ShurikenParticleRender: unknown renderMode Value.");
|
||
}
|
||
var parSys = this._owner.particleSystem;
|
||
(parSys) && (parSys._initBufferDatas());
|
||
}
|
||
}
|
||
get mesh() {
|
||
return this._mesh;
|
||
}
|
||
set mesh(value) {
|
||
if (this._mesh !== value) {
|
||
(this._mesh) && (this._mesh._removeReference());
|
||
this._mesh = value;
|
||
(value) && (value._addReference());
|
||
this._owner.particleSystem._initBufferDatas();
|
||
}
|
||
}
|
||
_calculateBoundingBox() {
|
||
var particleSystem = this._owner.particleSystem;
|
||
var bounds;
|
||
if (particleSystem._useCustomBounds) {
|
||
bounds = particleSystem.customBounds;
|
||
bounds._tranform(this._owner.transform.worldMatrix, this._bounds);
|
||
}
|
||
else if (particleSystem._simulationSupported()) {
|
||
particleSystem._generateBounds();
|
||
bounds = particleSystem._bounds;
|
||
bounds._tranform(this._owner.transform.worldMatrix, this._bounds);
|
||
if (particleSystem.gravityModifier != 0) {
|
||
var max = this._bounds.getMax();
|
||
var min = this._bounds.getMin();
|
||
var gravityOffset = particleSystem._gravityOffset;
|
||
max.y -= gravityOffset.x;
|
||
min.y -= gravityOffset.y;
|
||
this._bounds.setMax(max);
|
||
this._bounds.setMin(min);
|
||
}
|
||
}
|
||
else {
|
||
var min = this._bounds.getMin();
|
||
min.setValue(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
|
||
this._bounds.setMin(min);
|
||
var max = this._bounds.getMax();
|
||
max.setValue(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
|
||
this._bounds.setMax(max);
|
||
}
|
||
}
|
||
_needRender(boundFrustum, context) {
|
||
if (boundFrustum) {
|
||
if (boundFrustum.intersects(this.bounds._getBoundBox())) {
|
||
if (this._owner.particleSystem.isAlive)
|
||
return true;
|
||
else
|
||
return false;
|
||
}
|
||
else {
|
||
return false;
|
||
}
|
||
}
|
||
else {
|
||
return true;
|
||
}
|
||
}
|
||
_renderUpdate(context, transfrom) {
|
||
var particleSystem = this._owner.particleSystem;
|
||
var sv = this._shaderValues;
|
||
var transform = this._owner.transform;
|
||
switch (particleSystem.simulationSpace) {
|
||
case 0:
|
||
break;
|
||
case 1:
|
||
sv.setVector3(ShuriKenParticle3DShaderDeclaration.WORLDPOSITION, transform.position);
|
||
sv.setQuaternion(ShuriKenParticle3DShaderDeclaration.WORLDROTATION, transform.rotation);
|
||
break;
|
||
default:
|
||
throw new Error("ShurikenParticleMaterial: SimulationSpace value is invalid.");
|
||
}
|
||
switch (particleSystem.scaleMode) {
|
||
case 0:
|
||
var scale = transform.getWorldLossyScale();
|
||
sv.setVector3(ShuriKenParticle3DShaderDeclaration.POSITIONSCALE, scale);
|
||
sv.setVector3(ShuriKenParticle3DShaderDeclaration.SIZESCALE, scale);
|
||
break;
|
||
case 1:
|
||
var localScale = transform.localScale;
|
||
sv.setVector3(ShuriKenParticle3DShaderDeclaration.POSITIONSCALE, localScale);
|
||
sv.setVector3(ShuriKenParticle3DShaderDeclaration.SIZESCALE, localScale);
|
||
break;
|
||
case 2:
|
||
sv.setVector3(ShuriKenParticle3DShaderDeclaration.POSITIONSCALE, transform.getWorldLossyScale());
|
||
sv.setVector3(ShuriKenParticle3DShaderDeclaration.SIZESCALE, Vector3._ONE);
|
||
break;
|
||
}
|
||
Vector3.scale(Physics3DUtils.gravity, particleSystem.gravityModifier, this._finalGravity);
|
||
sv.setVector3(ShuriKenParticle3DShaderDeclaration.GRAVITY, this._finalGravity);
|
||
sv.setInt(ShuriKenParticle3DShaderDeclaration.SIMULATIONSPACE, particleSystem.simulationSpace);
|
||
sv.setBool(ShuriKenParticle3DShaderDeclaration.THREEDSTARTROTATION, particleSystem.threeDStartRotation);
|
||
sv.setInt(ShuriKenParticle3DShaderDeclaration.SCALINGMODE, particleSystem.scaleMode);
|
||
sv.setNumber(ShuriKenParticle3DShaderDeclaration.STRETCHEDBILLBOARDLENGTHSCALE, this.stretchedBillboardLengthScale);
|
||
sv.setNumber(ShuriKenParticle3DShaderDeclaration.STRETCHEDBILLBOARDSPEEDSCALE, this.stretchedBillboardSpeedScale);
|
||
sv.setNumber(ShuriKenParticle3DShaderDeclaration.CURRENTTIME, particleSystem._currentTime);
|
||
}
|
||
get bounds() {
|
||
if (this._boundsChange) {
|
||
this._calculateBoundingBox();
|
||
this._boundsChange = false;
|
||
}
|
||
return this._bounds;
|
||
}
|
||
_destroy() {
|
||
super._destroy();
|
||
(this._mesh) && (this._mesh._removeReference(), this._mesh = null);
|
||
}
|
||
}
|
||
|
||
class VertexShuriKenParticle {
|
||
constructor() {
|
||
}
|
||
}
|
||
VertexShuriKenParticle.PARTICLE_CORNERTEXTURECOORDINATE0 = 5;
|
||
VertexShuriKenParticle.PARTICLE_POSITION0 = 1;
|
||
VertexShuriKenParticle.PARTICLE_COLOR0 = 2;
|
||
VertexShuriKenParticle.PARTICLE_TEXTURECOORDINATE0 = 3;
|
||
VertexShuriKenParticle.PARTICLE_SHAPEPOSITIONSTARTLIFETIME = 4;
|
||
VertexShuriKenParticle.PARTICLE_DIRECTIONTIME = 0;
|
||
VertexShuriKenParticle.PARTICLE_STARTCOLOR0 = 6;
|
||
VertexShuriKenParticle.PARTICLE_ENDCOLOR0 = 7;
|
||
VertexShuriKenParticle.PARTICLE_STARTSIZE = 8;
|
||
VertexShuriKenParticle.PARTICLE_STARTROTATION = 9;
|
||
VertexShuriKenParticle.PARTICLE_STARTSPEED = 10;
|
||
VertexShuriKenParticle.PARTICLE_RANDOM0 = 11;
|
||
VertexShuriKenParticle.PARTICLE_RANDOM1 = 12;
|
||
VertexShuriKenParticle.PARTICLE_SIMULATIONWORLDPOSTION = 13;
|
||
VertexShuriKenParticle.PARTICLE_SIMULATIONWORLDROTATION = 14;
|
||
|
||
class VertexShurikenParticleBillboard extends VertexShuriKenParticle {
|
||
constructor(cornerTextureCoordinate, positionStartLifeTime, velocity, startColor, startSize, startRotation0, startRotation1, startRotation2, ageAddScale, time, startSpeed, randoms0, randoms1, simulationWorldPostion) {
|
||
super();
|
||
this._cornerTextureCoordinate = cornerTextureCoordinate;
|
||
this._positionStartLifeTime = positionStartLifeTime;
|
||
this._velocity = velocity;
|
||
this._startColor = startColor;
|
||
this._startSize = startSize;
|
||
this._startRotation0 = startRotation0;
|
||
this._startRotation1 = startRotation1;
|
||
this._startRotation2 = startRotation2;
|
||
this._startLifeTime = ageAddScale;
|
||
this._time = time;
|
||
this._startSpeed = startSpeed;
|
||
this._randoms0 = randoms0;
|
||
this._randoms1 = randoms1;
|
||
this._simulationWorldPostion = simulationWorldPostion;
|
||
}
|
||
static get vertexDeclaration() {
|
||
return VertexShurikenParticleBillboard._vertexDeclaration;
|
||
}
|
||
static __init__() {
|
||
VertexShurikenParticleBillboard._vertexDeclaration = new VertexDeclaration(152, [new VertexElement(0, VertexElementFormat.Vector4, VertexShuriKenParticle.PARTICLE_CORNERTEXTURECOORDINATE0),
|
||
new VertexElement(16, VertexElementFormat.Vector4, VertexShuriKenParticle.PARTICLE_SHAPEPOSITIONSTARTLIFETIME),
|
||
new VertexElement(32, VertexElementFormat.Vector4, VertexShuriKenParticle.PARTICLE_DIRECTIONTIME),
|
||
new VertexElement(48, VertexElementFormat.Vector4, VertexShuriKenParticle.PARTICLE_STARTCOLOR0),
|
||
new VertexElement(64, VertexElementFormat.Vector3, VertexShuriKenParticle.PARTICLE_STARTSIZE),
|
||
new VertexElement(76, VertexElementFormat.Vector3, VertexShuriKenParticle.PARTICLE_STARTROTATION),
|
||
new VertexElement(88, VertexElementFormat.Single, VertexShuriKenParticle.PARTICLE_STARTSPEED),
|
||
new VertexElement(92, VertexElementFormat.Vector4, VertexShuriKenParticle.PARTICLE_RANDOM0),
|
||
new VertexElement(108, VertexElementFormat.Vector4, VertexShuriKenParticle.PARTICLE_RANDOM1),
|
||
new VertexElement(124, VertexElementFormat.Vector3, VertexShuriKenParticle.PARTICLE_SIMULATIONWORLDPOSTION),
|
||
new VertexElement(136, VertexElementFormat.Vector4, VertexShuriKenParticle.PARTICLE_SIMULATIONWORLDROTATION)]);
|
||
}
|
||
get cornerTextureCoordinate() {
|
||
return this._cornerTextureCoordinate;
|
||
}
|
||
get positionStartLifeTime() {
|
||
return this._positionStartLifeTime;
|
||
}
|
||
get velocity() {
|
||
return this._velocity;
|
||
}
|
||
get startColor() {
|
||
return this._startColor;
|
||
}
|
||
get startSize() {
|
||
return this._startSize;
|
||
}
|
||
get startRotation0() {
|
||
return this._startRotation0;
|
||
}
|
||
get startRotation1() {
|
||
return this._startRotation1;
|
||
}
|
||
get startRotation2() {
|
||
return this._startRotation2;
|
||
}
|
||
get startLifeTime() {
|
||
return this._startLifeTime;
|
||
}
|
||
get time() {
|
||
return this._time;
|
||
}
|
||
get startSpeed() {
|
||
return this._startSpeed;
|
||
}
|
||
get random0() {
|
||
return this._randoms0;
|
||
}
|
||
get random1() {
|
||
return this._randoms1;
|
||
}
|
||
get simulationWorldPostion() {
|
||
return this._simulationWorldPostion;
|
||
}
|
||
}
|
||
|
||
class VertexShurikenParticleMesh extends VertexShuriKenParticle {
|
||
constructor(cornerTextureCoordinate, positionStartLifeTime, velocity, startColor, startSize, startRotation0, startRotation1, startRotation2, ageAddScale, time, startSpeed, randoms0, randoms1, simulationWorldPostion) {
|
||
super();
|
||
this._cornerTextureCoordinate = cornerTextureCoordinate;
|
||
this._positionStartLifeTime = positionStartLifeTime;
|
||
this._velocity = velocity;
|
||
this._startColor = startColor;
|
||
this._startSize = startSize;
|
||
this._startRotation0 = startRotation0;
|
||
this._startRotation1 = startRotation1;
|
||
this._startRotation2 = startRotation2;
|
||
this._startLifeTime = ageAddScale;
|
||
this._time = time;
|
||
this._startSpeed = startSpeed;
|
||
this._randoms0 = randoms0;
|
||
this._randoms1 = randoms1;
|
||
this._simulationWorldPostion = simulationWorldPostion;
|
||
}
|
||
static __init__() {
|
||
VertexShurikenParticleMesh._vertexDeclaration = new VertexDeclaration(172, [new VertexElement(0, VertexElementFormat.Vector3, VertexShuriKenParticle.PARTICLE_POSITION0),
|
||
new VertexElement(12, VertexElementFormat.Vector4, VertexShuriKenParticle.PARTICLE_COLOR0),
|
||
new VertexElement(28, VertexElementFormat.Vector2, VertexShuriKenParticle.PARTICLE_TEXTURECOORDINATE0),
|
||
new VertexElement(36, VertexElementFormat.Vector4, VertexShuriKenParticle.PARTICLE_SHAPEPOSITIONSTARTLIFETIME),
|
||
new VertexElement(52, VertexElementFormat.Vector4, VertexShuriKenParticle.PARTICLE_DIRECTIONTIME),
|
||
new VertexElement(68, VertexElementFormat.Vector4, VertexShuriKenParticle.PARTICLE_STARTCOLOR0),
|
||
new VertexElement(84, VertexElementFormat.Vector3, VertexShuriKenParticle.PARTICLE_STARTSIZE),
|
||
new VertexElement(96, VertexElementFormat.Vector3, VertexShuriKenParticle.PARTICLE_STARTROTATION),
|
||
new VertexElement(108, VertexElementFormat.Single, VertexShuriKenParticle.PARTICLE_STARTSPEED),
|
||
new VertexElement(112, VertexElementFormat.Vector4, VertexShuriKenParticle.PARTICLE_RANDOM0),
|
||
new VertexElement(128, VertexElementFormat.Vector4, VertexShuriKenParticle.PARTICLE_RANDOM1),
|
||
new VertexElement(144, VertexElementFormat.Vector3, VertexShuriKenParticle.PARTICLE_SIMULATIONWORLDPOSTION),
|
||
new VertexElement(156, VertexElementFormat.Vector4, VertexShuriKenParticle.PARTICLE_SIMULATIONWORLDROTATION)]);
|
||
}
|
||
static get vertexDeclaration() {
|
||
return VertexShurikenParticleMesh._vertexDeclaration;
|
||
}
|
||
get cornerTextureCoordinate() {
|
||
return this._cornerTextureCoordinate;
|
||
}
|
||
get position() {
|
||
return this._positionStartLifeTime;
|
||
}
|
||
get velocity() {
|
||
return this._velocity;
|
||
}
|
||
get startColor() {
|
||
return this._startColor;
|
||
}
|
||
get startSize() {
|
||
return this._startSize;
|
||
}
|
||
get startRotation0() {
|
||
return this._startRotation0;
|
||
}
|
||
get startRotation1() {
|
||
return this._startRotation1;
|
||
}
|
||
get startRotation2() {
|
||
return this._startRotation2;
|
||
}
|
||
get startLifeTime() {
|
||
return this._startLifeTime;
|
||
}
|
||
get time() {
|
||
return this._time;
|
||
}
|
||
get startSpeed() {
|
||
return this._startSpeed;
|
||
}
|
||
get random0() {
|
||
return this._randoms0;
|
||
}
|
||
get random1() {
|
||
return this._randoms1;
|
||
}
|
||
get simulationWorldPostion() {
|
||
return this._simulationWorldPostion;
|
||
}
|
||
}
|
||
|
||
class Rand {
|
||
constructor(seed) {
|
||
this._temp = new Uint32Array(1);
|
||
this.seeds = new Uint32Array(4);
|
||
this.seeds[0] = seed;
|
||
this.seeds[1] = this.seeds[0] * 0x6C078965 + 1;
|
||
this.seeds[2] = this.seeds[1] * 0x6C078965 + 1;
|
||
this.seeds[3] = this.seeds[2] * 0x6C078965 + 1;
|
||
}
|
||
static getFloatFromInt(v) {
|
||
return (v & 0x007FFFFF) * (1.0 / 8388607.0);
|
||
}
|
||
static getByteFromInt(v) {
|
||
return (v & 0x007FFFFF) >>> 15;
|
||
}
|
||
get seed() {
|
||
return this.seeds[0];
|
||
}
|
||
set seed(seed) {
|
||
this.seeds[0] = seed;
|
||
this.seeds[1] = this.seeds[0] * 0x6C078965 + 1;
|
||
this.seeds[2] = this.seeds[1] * 0x6C078965 + 1;
|
||
this.seeds[3] = this.seeds[2] * 0x6C078965 + 1;
|
||
}
|
||
getUint() {
|
||
this._temp[0] = this.seeds[0] ^ (this.seeds[0] << 11);
|
||
this.seeds[0] = this.seeds[1];
|
||
this.seeds[1] = this.seeds[2];
|
||
this.seeds[2] = this.seeds[3];
|
||
this.seeds[3] = (this.seeds[3] ^ (this.seeds[3] >>> 19)) ^ (this._temp[0] ^ (this._temp[0] >>> 8));
|
||
return this.seeds[3];
|
||
}
|
||
getFloat() {
|
||
this.getUint();
|
||
return (this.seeds[3] & 0x007FFFFF) * (1.0 / 8388607.0);
|
||
}
|
||
getSignedFloat() {
|
||
return this.getFloat() * 2.0 - 1.0;
|
||
}
|
||
}
|
||
|
||
class Emission {
|
||
constructor() {
|
||
this._emissionRate = 10;
|
||
this._destroyed = false;
|
||
this._bursts = [];
|
||
}
|
||
set emissionRate(value) {
|
||
if (value < 0)
|
||
throw new Error("ParticleBaseShape:emissionRate value must large or equal than 0.");
|
||
this._emissionRate = value;
|
||
}
|
||
get emissionRate() {
|
||
return this._emissionRate;
|
||
}
|
||
get destroyed() {
|
||
return this._destroyed;
|
||
}
|
||
destroy() {
|
||
this._bursts = null;
|
||
this._destroyed = true;
|
||
}
|
||
getBurstsCount() {
|
||
return this._bursts.length;
|
||
}
|
||
getBurstByIndex(index) {
|
||
return this._bursts[index];
|
||
}
|
||
addBurst(burst) {
|
||
var burstsCount = this._bursts.length;
|
||
if (burstsCount > 0)
|
||
for (var i = 0; i < burstsCount; i++) {
|
||
if (this._bursts[i].time > burst.time)
|
||
this._bursts.splice(i, 0, burst);
|
||
}
|
||
this._bursts.push(burst);
|
||
}
|
||
removeBurst(burst) {
|
||
var index = this._bursts.indexOf(burst);
|
||
if (index !== -1) {
|
||
this._bursts.splice(index, 1);
|
||
}
|
||
}
|
||
removeBurstByIndex(index) {
|
||
this._bursts.splice(index, 1);
|
||
}
|
||
clearBurst() {
|
||
this._bursts.length = 0;
|
||
}
|
||
cloneTo(destObject) {
|
||
var destEmission = destObject;
|
||
var destBursts = destEmission._bursts;
|
||
destBursts.length = this._bursts.length;
|
||
for (var i = 0, n = this._bursts.length; i < n; i++) {
|
||
var destBurst = destBursts[i];
|
||
if (destBurst)
|
||
this._bursts[i].cloneTo(destBurst);
|
||
else
|
||
destBursts[i] = this._bursts[i].clone();
|
||
}
|
||
destEmission._emissionRate = this._emissionRate;
|
||
destEmission.enable = this.enable;
|
||
}
|
||
clone() {
|
||
var destEmission = new Emission();
|
||
this.cloneTo(destEmission);
|
||
return destEmission;
|
||
}
|
||
}
|
||
|
||
class ShurikenParticleData {
|
||
constructor() {
|
||
}
|
||
static _getStartLifetimeFromGradient(startLifeTimeGradient, emissionTime) {
|
||
for (var i = 1, n = startLifeTimeGradient.gradientCount; i < n; i++) {
|
||
var key = startLifeTimeGradient.getKeyByIndex(i);
|
||
if (key >= emissionTime) {
|
||
var lastKey = startLifeTimeGradient.getKeyByIndex(i - 1);
|
||
var age = (emissionTime - lastKey) / (key - lastKey);
|
||
return Laya.MathUtil.lerp(startLifeTimeGradient.getValueByIndex(i - 1), startLifeTimeGradient.getValueByIndex(i), age);
|
||
}
|
||
}
|
||
throw new Error("ShurikenParticleData: can't get value foam startLifeTimeGradient.");
|
||
}
|
||
static _randomInvertRoationArray(rotatonE, outE, randomizeRotationDirection, rand, randomSeeds) {
|
||
var randDic;
|
||
if (rand) {
|
||
rand.seed = randomSeeds[6];
|
||
randDic = rand.getFloat();
|
||
randomSeeds[6] = rand.seed;
|
||
}
|
||
else {
|
||
randDic = Math.random();
|
||
}
|
||
if (randDic < randomizeRotationDirection) {
|
||
outE.x = -rotatonE.x;
|
||
outE.y = -rotatonE.y;
|
||
outE.z = -rotatonE.z;
|
||
}
|
||
else {
|
||
outE.x = rotatonE.x;
|
||
outE.y = rotatonE.y;
|
||
outE.z = rotatonE.z;
|
||
}
|
||
}
|
||
static _randomInvertRoation(rotaton, randomizeRotationDirection, rand, randomSeeds) {
|
||
var randDic;
|
||
if (rand) {
|
||
rand.seed = randomSeeds[6];
|
||
randDic = rand.getFloat();
|
||
randomSeeds[6] = rand.seed;
|
||
}
|
||
else {
|
||
randDic = Math.random();
|
||
}
|
||
if (randDic < randomizeRotationDirection)
|
||
rotaton = -rotaton;
|
||
return rotaton;
|
||
}
|
||
static create(particleSystem, particleRender) {
|
||
var autoRandomSeed = particleSystem.autoRandomSeed;
|
||
var rand = particleSystem._rand;
|
||
var randomSeeds = particleSystem._randomSeeds;
|
||
switch (particleSystem.startColorType) {
|
||
case 0:
|
||
var constantStartColor = particleSystem.startColorConstant;
|
||
ShurikenParticleData.startColor.x = constantStartColor.x;
|
||
ShurikenParticleData.startColor.y = constantStartColor.y;
|
||
ShurikenParticleData.startColor.z = constantStartColor.z;
|
||
ShurikenParticleData.startColor.w = constantStartColor.w;
|
||
break;
|
||
case 2:
|
||
if (autoRandomSeed) {
|
||
Vector4.lerp(particleSystem.startColorConstantMin, particleSystem.startColorConstantMax, Math.random(), ShurikenParticleData.startColor);
|
||
}
|
||
else {
|
||
rand.seed = randomSeeds[3];
|
||
Vector4.lerp(particleSystem.startColorConstantMin, particleSystem.startColorConstantMax, rand.getFloat(), ShurikenParticleData.startColor);
|
||
randomSeeds[3] = rand.seed;
|
||
}
|
||
break;
|
||
}
|
||
var colorOverLifetime = particleSystem.colorOverLifetime;
|
||
if (colorOverLifetime && colorOverLifetime.enable) {
|
||
var color = colorOverLifetime.color;
|
||
switch (color.type) {
|
||
case 0:
|
||
ShurikenParticleData.startColor.x = ShurikenParticleData.startColor.x * color.constant.x;
|
||
ShurikenParticleData.startColor.y = ShurikenParticleData.startColor.y * color.constant.y;
|
||
ShurikenParticleData.startColor.z = ShurikenParticleData.startColor.z * color.constant.z;
|
||
ShurikenParticleData.startColor.w = ShurikenParticleData.startColor.w * color.constant.w;
|
||
break;
|
||
case 2:
|
||
var colorRandom;
|
||
if (autoRandomSeed) {
|
||
colorRandom = Math.random();
|
||
}
|
||
else {
|
||
rand.seed = randomSeeds[10];
|
||
colorRandom = rand.getFloat();
|
||
randomSeeds[10] = rand.seed;
|
||
}
|
||
var minConstantColor = color.constantMin;
|
||
var maxConstantColor = color.constantMax;
|
||
ShurikenParticleData.startColor.x = ShurikenParticleData.startColor.x * Laya.MathUtil.lerp(minConstantColor.x, maxConstantColor.x, colorRandom);
|
||
ShurikenParticleData.startColor.y = ShurikenParticleData.startColor.y * Laya.MathUtil.lerp(minConstantColor.y, maxConstantColor.y, colorRandom);
|
||
ShurikenParticleData.startColor.z = ShurikenParticleData.startColor.z * Laya.MathUtil.lerp(minConstantColor.z, maxConstantColor.z, colorRandom);
|
||
ShurikenParticleData.startColor.w = ShurikenParticleData.startColor.w * Laya.MathUtil.lerp(minConstantColor.w, maxConstantColor.w, colorRandom);
|
||
break;
|
||
}
|
||
}
|
||
var particleSize = ShurikenParticleData.startSize;
|
||
switch (particleSystem.startSizeType) {
|
||
case 0:
|
||
if (particleSystem.threeDStartSize) {
|
||
var startSizeConstantSeparate = particleSystem.startSizeConstantSeparate;
|
||
particleSize[0] = startSizeConstantSeparate.x;
|
||
particleSize[1] = startSizeConstantSeparate.y;
|
||
particleSize[2] = startSizeConstantSeparate.z;
|
||
}
|
||
else {
|
||
particleSize[0] = particleSize[1] = particleSize[2] = particleSystem.startSizeConstant;
|
||
}
|
||
break;
|
||
case 2:
|
||
if (particleSystem.threeDStartSize) {
|
||
var startSizeConstantMinSeparate = particleSystem.startSizeConstantMinSeparate;
|
||
var startSizeConstantMaxSeparate = particleSystem.startSizeConstantMaxSeparate;
|
||
if (autoRandomSeed) {
|
||
particleSize[0] = Laya.MathUtil.lerp(startSizeConstantMinSeparate.x, startSizeConstantMaxSeparate.x, Math.random());
|
||
particleSize[1] = Laya.MathUtil.lerp(startSizeConstantMinSeparate.y, startSizeConstantMaxSeparate.y, Math.random());
|
||
particleSize[2] = Laya.MathUtil.lerp(startSizeConstantMinSeparate.z, startSizeConstantMaxSeparate.z, Math.random());
|
||
}
|
||
else {
|
||
rand.seed = randomSeeds[4];
|
||
particleSize[0] = Laya.MathUtil.lerp(startSizeConstantMinSeparate.x, startSizeConstantMaxSeparate.x, rand.getFloat());
|
||
particleSize[1] = Laya.MathUtil.lerp(startSizeConstantMinSeparate.y, startSizeConstantMaxSeparate.y, rand.getFloat());
|
||
particleSize[2] = Laya.MathUtil.lerp(startSizeConstantMinSeparate.z, startSizeConstantMaxSeparate.z, rand.getFloat());
|
||
randomSeeds[4] = rand.seed;
|
||
}
|
||
}
|
||
else {
|
||
if (autoRandomSeed) {
|
||
particleSize[0] = particleSize[1] = particleSize[2] = Laya.MathUtil.lerp(particleSystem.startSizeConstantMin, particleSystem.startSizeConstantMax, Math.random());
|
||
}
|
||
else {
|
||
rand.seed = randomSeeds[4];
|
||
particleSize[0] = particleSize[1] = particleSize[2] = Laya.MathUtil.lerp(particleSystem.startSizeConstantMin, particleSystem.startSizeConstantMax, rand.getFloat());
|
||
randomSeeds[4] = rand.seed;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
var sizeOverLifetime = particleSystem.sizeOverLifetime;
|
||
if (sizeOverLifetime && sizeOverLifetime.enable && sizeOverLifetime.size.type === 1) {
|
||
var size = sizeOverLifetime.size;
|
||
if (size.separateAxes) {
|
||
if (autoRandomSeed) {
|
||
particleSize[0] = particleSize[0] * Laya.MathUtil.lerp(size.constantMinSeparate.x, size.constantMaxSeparate.x, Math.random());
|
||
particleSize[1] = particleSize[1] * Laya.MathUtil.lerp(size.constantMinSeparate.y, size.constantMaxSeparate.y, Math.random());
|
||
particleSize[2] = particleSize[2] * Laya.MathUtil.lerp(size.constantMinSeparate.z, size.constantMaxSeparate.z, Math.random());
|
||
}
|
||
else {
|
||
rand.seed = randomSeeds[11];
|
||
particleSize[0] = particleSize[0] * Laya.MathUtil.lerp(size.constantMinSeparate.x, size.constantMaxSeparate.x, rand.getFloat());
|
||
particleSize[1] = particleSize[1] * Laya.MathUtil.lerp(size.constantMinSeparate.y, size.constantMaxSeparate.y, rand.getFloat());
|
||
particleSize[2] = particleSize[2] * Laya.MathUtil.lerp(size.constantMinSeparate.z, size.constantMaxSeparate.z, rand.getFloat());
|
||
randomSeeds[11] = rand.seed;
|
||
}
|
||
}
|
||
else {
|
||
var randomSize;
|
||
if (autoRandomSeed) {
|
||
randomSize = Laya.MathUtil.lerp(size.constantMin, size.constantMax, Math.random());
|
||
}
|
||
else {
|
||
rand.seed = randomSeeds[11];
|
||
randomSize = Laya.MathUtil.lerp(size.constantMin, size.constantMax, rand.getFloat());
|
||
randomSeeds[11] = rand.seed;
|
||
}
|
||
particleSize[0] = particleSize[0] * randomSize;
|
||
particleSize[1] = particleSize[1] * randomSize;
|
||
particleSize[2] = particleSize[2] * randomSize;
|
||
}
|
||
}
|
||
var renderMode = particleRender.renderMode;
|
||
if (renderMode !== 1) {
|
||
switch (particleSystem.startRotationType) {
|
||
case 0:
|
||
if (particleSystem.threeDStartRotation) {
|
||
var startRotationConstantSeparate = particleSystem.startRotationConstantSeparate;
|
||
var randomRotationE = ShurikenParticleData._tempVector30;
|
||
ShurikenParticleData._randomInvertRoationArray(startRotationConstantSeparate, randomRotationE, particleSystem.randomizeRotationDirection, autoRandomSeed ? null : rand, randomSeeds);
|
||
ShurikenParticleData.startRotation[0] = randomRotationE.x;
|
||
ShurikenParticleData.startRotation[1] = randomRotationE.y;
|
||
if (renderMode !== 4)
|
||
ShurikenParticleData.startRotation[2] = -randomRotationE.z;
|
||
else
|
||
ShurikenParticleData.startRotation[2] = randomRotationE.z;
|
||
}
|
||
else {
|
||
ShurikenParticleData.startRotation[0] = ShurikenParticleData._randomInvertRoation(particleSystem.startRotationConstant, particleSystem.randomizeRotationDirection, autoRandomSeed ? null : rand, randomSeeds);
|
||
ShurikenParticleData.startRotation[1] = 0;
|
||
ShurikenParticleData.startRotation[2] = 0;
|
||
}
|
||
break;
|
||
case 2:
|
||
if (particleSystem.threeDStartRotation) {
|
||
var startRotationConstantMinSeparate = particleSystem.startRotationConstantMinSeparate;
|
||
var startRotationConstantMaxSeparate = particleSystem.startRotationConstantMaxSeparate;
|
||
var lerpRoationE = ShurikenParticleData._tempVector30;
|
||
if (autoRandomSeed) {
|
||
lerpRoationE.x = Laya.MathUtil.lerp(startRotationConstantMinSeparate.x, startRotationConstantMaxSeparate.x, Math.random());
|
||
lerpRoationE.y = Laya.MathUtil.lerp(startRotationConstantMinSeparate.y, startRotationConstantMaxSeparate.y, Math.random());
|
||
lerpRoationE.z = Laya.MathUtil.lerp(startRotationConstantMinSeparate.z, startRotationConstantMaxSeparate.z, Math.random());
|
||
}
|
||
else {
|
||
rand.seed = randomSeeds[5];
|
||
lerpRoationE.x = Laya.MathUtil.lerp(startRotationConstantMinSeparate.x, startRotationConstantMaxSeparate.x, rand.getFloat());
|
||
lerpRoationE.y = Laya.MathUtil.lerp(startRotationConstantMinSeparate.y, startRotationConstantMaxSeparate.y, rand.getFloat());
|
||
lerpRoationE.z = Laya.MathUtil.lerp(startRotationConstantMinSeparate.z, startRotationConstantMaxSeparate.z, rand.getFloat());
|
||
randomSeeds[5] = rand.seed;
|
||
}
|
||
ShurikenParticleData._randomInvertRoationArray(lerpRoationE, lerpRoationE, particleSystem.randomizeRotationDirection, autoRandomSeed ? null : rand, randomSeeds);
|
||
ShurikenParticleData.startRotation[0] = lerpRoationE.x;
|
||
ShurikenParticleData.startRotation[1] = lerpRoationE.y;
|
||
if (renderMode !== 4)
|
||
ShurikenParticleData.startRotation[2] = -lerpRoationE.z;
|
||
else
|
||
ShurikenParticleData.startRotation[2] = lerpRoationE.z;
|
||
}
|
||
else {
|
||
if (autoRandomSeed) {
|
||
ShurikenParticleData.startRotation[0] = ShurikenParticleData._randomInvertRoation(Laya.MathUtil.lerp(particleSystem.startRotationConstantMin, particleSystem.startRotationConstantMax, Math.random()), particleSystem.randomizeRotationDirection, autoRandomSeed ? null : rand, randomSeeds);
|
||
}
|
||
else {
|
||
rand.seed = randomSeeds[5];
|
||
ShurikenParticleData.startRotation[0] = ShurikenParticleData._randomInvertRoation(Laya.MathUtil.lerp(particleSystem.startRotationConstantMin, particleSystem.startRotationConstantMax, rand.getFloat()), particleSystem.randomizeRotationDirection, autoRandomSeed ? null : rand, randomSeeds);
|
||
randomSeeds[5] = rand.seed;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
switch (particleSystem.startLifetimeType) {
|
||
case 0:
|
||
ShurikenParticleData.startLifeTime = particleSystem.startLifetimeConstant;
|
||
break;
|
||
case 1:
|
||
ShurikenParticleData.startLifeTime = ShurikenParticleData._getStartLifetimeFromGradient(particleSystem.startLifeTimeGradient, particleSystem.emissionTime);
|
||
break;
|
||
case 2:
|
||
if (autoRandomSeed) {
|
||
ShurikenParticleData.startLifeTime = Laya.MathUtil.lerp(particleSystem.startLifetimeConstantMin, particleSystem.startLifetimeConstantMax, Math.random());
|
||
}
|
||
else {
|
||
rand.seed = randomSeeds[7];
|
||
ShurikenParticleData.startLifeTime = Laya.MathUtil.lerp(particleSystem.startLifetimeConstantMin, particleSystem.startLifetimeConstantMax, rand.getFloat());
|
||
randomSeeds[7] = rand.seed;
|
||
}
|
||
break;
|
||
case 3:
|
||
var emissionTime = particleSystem.emissionTime;
|
||
if (autoRandomSeed) {
|
||
ShurikenParticleData.startLifeTime = Laya.MathUtil.lerp(ShurikenParticleData._getStartLifetimeFromGradient(particleSystem.startLifeTimeGradientMin, emissionTime), ShurikenParticleData._getStartLifetimeFromGradient(particleSystem.startLifeTimeGradientMax, emissionTime), Math.random());
|
||
}
|
||
else {
|
||
rand.seed = randomSeeds[7];
|
||
ShurikenParticleData.startLifeTime = Laya.MathUtil.lerp(ShurikenParticleData._getStartLifetimeFromGradient(particleSystem.startLifeTimeGradientMin, emissionTime), ShurikenParticleData._getStartLifetimeFromGradient(particleSystem.startLifeTimeGradientMax, emissionTime), rand.getFloat());
|
||
randomSeeds[7] = rand.seed;
|
||
}
|
||
break;
|
||
}
|
||
var textureSheetAnimation = particleSystem.textureSheetAnimation;
|
||
var enableSheetAnimation = textureSheetAnimation && textureSheetAnimation.enable;
|
||
if (enableSheetAnimation) {
|
||
var title = textureSheetAnimation.tiles;
|
||
var titleX = title.x, titleY = title.y;
|
||
var subU = 1.0 / titleX, subV = 1.0 / titleY;
|
||
var startFrameCount;
|
||
var startFrame = textureSheetAnimation.startFrame;
|
||
switch (startFrame.type) {
|
||
case 0:
|
||
startFrameCount = startFrame.constant;
|
||
break;
|
||
case 1:
|
||
if (autoRandomSeed) {
|
||
startFrameCount = Laya.MathUtil.lerp(startFrame.constantMin, startFrame.constantMax, Math.random());
|
||
}
|
||
else {
|
||
rand.seed = randomSeeds[14];
|
||
startFrameCount = Laya.MathUtil.lerp(startFrame.constantMin, startFrame.constantMax, rand.getFloat());
|
||
randomSeeds[14] = rand.seed;
|
||
}
|
||
break;
|
||
}
|
||
var frame = textureSheetAnimation.frame;
|
||
var cycles = textureSheetAnimation.cycles;
|
||
switch (frame.type) {
|
||
case 0:
|
||
startFrameCount += frame.constant * cycles;
|
||
break;
|
||
case 2:
|
||
if (autoRandomSeed) {
|
||
startFrameCount += Laya.MathUtil.lerp(frame.constantMin, frame.constantMax, Math.random()) * cycles;
|
||
}
|
||
else {
|
||
rand.seed = randomSeeds[15];
|
||
startFrameCount += Laya.MathUtil.lerp(frame.constantMin, frame.constantMax, rand.getFloat()) * cycles;
|
||
randomSeeds[15] = rand.seed;
|
||
}
|
||
break;
|
||
}
|
||
var startRow = 0;
|
||
switch (textureSheetAnimation.type) {
|
||
case 0:
|
||
startRow = Math.floor(startFrameCount / titleX);
|
||
break;
|
||
case 1:
|
||
if (textureSheetAnimation.randomRow) {
|
||
if (autoRandomSeed) {
|
||
startRow = Math.floor(Math.random() * titleY);
|
||
}
|
||
else {
|
||
rand.seed = randomSeeds[13];
|
||
startRow = Math.floor(rand.getFloat() * titleY);
|
||
randomSeeds[13] = rand.seed;
|
||
}
|
||
}
|
||
else {
|
||
startRow = textureSheetAnimation.rowIndex;
|
||
}
|
||
break;
|
||
}
|
||
var startCol = Math.floor(startFrameCount % titleX);
|
||
ShurikenParticleData.startUVInfo = ShurikenParticleData.startUVInfo;
|
||
ShurikenParticleData.startUVInfo[0] = subU;
|
||
ShurikenParticleData.startUVInfo[1] = subV;
|
||
ShurikenParticleData.startUVInfo[2] = startCol * subU;
|
||
ShurikenParticleData.startUVInfo[3] = startRow * subV;
|
||
}
|
||
else {
|
||
ShurikenParticleData.startUVInfo = ShurikenParticleData.startUVInfo;
|
||
ShurikenParticleData.startUVInfo[0] = 1.0;
|
||
ShurikenParticleData.startUVInfo[1] = 1.0;
|
||
ShurikenParticleData.startUVInfo[2] = 0.0;
|
||
ShurikenParticleData.startUVInfo[3] = 0.0;
|
||
}
|
||
}
|
||
}
|
||
ShurikenParticleData._tempVector30 = new Vector3();
|
||
ShurikenParticleData.startColor = new Vector4();
|
||
ShurikenParticleData.startSize = new Float32Array(3);
|
||
ShurikenParticleData.startRotation = new Float32Array(3);
|
||
ShurikenParticleData.startUVInfo = new Float32Array(4);
|
||
|
||
class ShurikenParticleSystem extends GeometryElement {
|
||
constructor(owner) {
|
||
super();
|
||
this._boundingSphere = null;
|
||
this._boundingBox = null;
|
||
this._boundingBoxCorners = null;
|
||
this._bounds = null;
|
||
this._gravityOffset = new Vector2();
|
||
this._customBounds = null;
|
||
this._useCustomBounds = false;
|
||
this._owner = null;
|
||
this._ownerRender = null;
|
||
this._vertices = null;
|
||
this._floatCountPerVertex = 0;
|
||
this._startLifeTimeIndex = 0;
|
||
this._timeIndex = 0;
|
||
this._simulateUpdate = false;
|
||
this._firstActiveElement = 0;
|
||
this._firstNewElement = 0;
|
||
this._firstFreeElement = 0;
|
||
this._firstRetiredElement = 0;
|
||
this._drawCounter = 0;
|
||
this._bufferMaxParticles = 0;
|
||
this._emission = null;
|
||
this._shape = null;
|
||
this._isEmitting = false;
|
||
this._isPlaying = false;
|
||
this._isPaused = false;
|
||
this._playStartDelay = 0;
|
||
this._frameRateTime = 0;
|
||
this._emissionTime = 0;
|
||
this._totalDelayTime = 0;
|
||
this._burstsIndex = 0;
|
||
this._velocityOverLifetime = null;
|
||
this._colorOverLifetime = null;
|
||
this._sizeOverLifetime = null;
|
||
this._rotationOverLifetime = null;
|
||
this._textureSheetAnimation = null;
|
||
this._startLifetimeType = 0;
|
||
this._startLifetimeConstant = 0;
|
||
this._startLifeTimeGradient = null;
|
||
this._startLifetimeConstantMin = 0;
|
||
this._startLifetimeConstantMax = 0;
|
||
this._startLifeTimeGradientMin = null;
|
||
this._startLifeTimeGradientMax = null;
|
||
this._maxStartLifetime = 0;
|
||
this._uvLength = new Vector2();
|
||
this._vertexStride = 0;
|
||
this._indexStride = 0;
|
||
this._vertexBuffer = null;
|
||
this._indexBuffer = null;
|
||
this._bufferState = new BufferState();
|
||
this._updateMask = 0;
|
||
this._currentTime = 0;
|
||
this._startUpdateLoopCount = 0;
|
||
this._rand = null;
|
||
this._randomSeeds = null;
|
||
this.duration = 0;
|
||
this.looping = false;
|
||
this.prewarm = false;
|
||
this.startDelayType = 0;
|
||
this.startDelay = 0;
|
||
this.startDelayMin = 0;
|
||
this.startDelayMax = 0;
|
||
this.startSpeedType = 0;
|
||
this.startSpeedConstant = 0;
|
||
this.startSpeedConstantMin = 0;
|
||
this.startSpeedConstantMax = 0;
|
||
this.threeDStartSize = false;
|
||
this.startSizeType = 0;
|
||
this.startSizeConstant = 0;
|
||
this.startSizeConstantSeparate = null;
|
||
this.startSizeConstantMin = 0;
|
||
this.startSizeConstantMax = 0;
|
||
this.startSizeConstantMinSeparate = null;
|
||
this.startSizeConstantMaxSeparate = null;
|
||
this.threeDStartRotation = false;
|
||
this.startRotationType = 0;
|
||
this.startRotationConstant = 0;
|
||
this.startRotationConstantSeparate = null;
|
||
this.startRotationConstantMin = 0;
|
||
this.startRotationConstantMax = 0;
|
||
this.startRotationConstantMinSeparate = null;
|
||
this.startRotationConstantMaxSeparate = null;
|
||
this.randomizeRotationDirection = 0;
|
||
this.startColorType = 0;
|
||
this.startColorConstant = new Vector4(1, 1, 1, 1);
|
||
this.startColorConstantMin = new Vector4(0, 0, 0, 0);
|
||
this.startColorConstantMax = new Vector4(1, 1, 1, 1);
|
||
this.gravityModifier = 0;
|
||
this.simulationSpace = 0;
|
||
this.simulationSpeed = 1.0;
|
||
this.scaleMode = 1;
|
||
this.playOnAwake = false;
|
||
this.randomSeed = null;
|
||
this.autoRandomSeed = false;
|
||
this.isPerformanceMode = false;
|
||
this._firstActiveElement = 0;
|
||
this._firstNewElement = 0;
|
||
this._firstFreeElement = 0;
|
||
this._firstRetiredElement = 0;
|
||
this._owner = owner;
|
||
this._ownerRender = owner.particleRenderer;
|
||
this._boundingBoxCorners = [];
|
||
this._boundingSphere = new BoundSphere(new Vector3(), Number.MAX_VALUE);
|
||
this._boundingBox = new BoundBox(new Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE), new Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE));
|
||
this._bounds = new Bounds(this._boundingBox.min, this._boundingBox.max);
|
||
this._useCustomBounds = false;
|
||
this._currentTime = 0;
|
||
this._isEmitting = false;
|
||
this._isPlaying = false;
|
||
this._isPaused = false;
|
||
this._burstsIndex = 0;
|
||
this._frameRateTime = 0;
|
||
this._emissionTime = 0;
|
||
this._totalDelayTime = 0;
|
||
this._simulateUpdate = false;
|
||
this._bufferMaxParticles = 1;
|
||
this.duration = 5.0;
|
||
this.looping = true;
|
||
this.prewarm = false;
|
||
this.startDelayType = 0;
|
||
this.startDelay = 0.0;
|
||
this.startDelayMin = 0.0;
|
||
this.startDelayMax = 0.0;
|
||
this._startLifetimeType = 0;
|
||
this._startLifetimeConstant = 5.0;
|
||
this._startLifeTimeGradient = new GradientDataNumber();
|
||
this._startLifetimeConstantMin = 0.0;
|
||
this._startLifetimeConstantMax = 5.0;
|
||
this._startLifeTimeGradientMin = new GradientDataNumber();
|
||
this._startLifeTimeGradientMax = new GradientDataNumber();
|
||
this._maxStartLifetime = 5.0;
|
||
this.startSpeedType = 0;
|
||
this.startSpeedConstant = 5.0;
|
||
this.startSpeedConstantMin = 0.0;
|
||
this.startSpeedConstantMax = 5.0;
|
||
this.threeDStartSize = false;
|
||
this.startSizeType = 0;
|
||
this.startSizeConstant = 1;
|
||
this.startSizeConstantSeparate = new Vector3(1, 1, 1);
|
||
this.startSizeConstantMin = 0;
|
||
this.startSizeConstantMax = 1;
|
||
this.startSizeConstantMinSeparate = new Vector3(0, 0, 0);
|
||
this.startSizeConstantMaxSeparate = new Vector3(1, 1, 1);
|
||
this.threeDStartRotation = false;
|
||
this.startRotationType = 0;
|
||
this.startRotationConstant = 0;
|
||
this.startRotationConstantSeparate = new Vector3(0, 0, 0);
|
||
this.startRotationConstantMin = 0.0;
|
||
this.startRotationConstantMax = 0.0;
|
||
this.startRotationConstantMinSeparate = new Vector3(0, 0, 0);
|
||
this.startRotationConstantMaxSeparate = new Vector3(0, 0, 0);
|
||
this.gravityModifier = 0.0;
|
||
this.simulationSpace = 1;
|
||
this.scaleMode = 1;
|
||
this.playOnAwake = true;
|
||
this._rand = new Rand(0);
|
||
this.autoRandomSeed = true;
|
||
this.randomSeed = new Uint32Array(1);
|
||
this._randomSeeds = new Uint32Array(ShurikenParticleSystem._RANDOMOFFSET.length);
|
||
this.isPerformanceMode = true;
|
||
this._emission = new Emission();
|
||
this._emission.enable = true;
|
||
}
|
||
;
|
||
get maxParticles() {
|
||
return this._bufferMaxParticles - 1;
|
||
}
|
||
set maxParticles(value) {
|
||
var newMaxParticles = value + 1;
|
||
if (newMaxParticles !== this._bufferMaxParticles) {
|
||
this._bufferMaxParticles = newMaxParticles;
|
||
this._initBufferDatas();
|
||
}
|
||
}
|
||
get emission() {
|
||
return this._emission;
|
||
}
|
||
get aliveParticleCount() {
|
||
if (this._firstNewElement >= this._firstRetiredElement)
|
||
return this._firstNewElement - this._firstRetiredElement;
|
||
else
|
||
return this._bufferMaxParticles - this._firstRetiredElement + this._firstNewElement;
|
||
}
|
||
get emissionTime() {
|
||
return this._emissionTime > this.duration ? this.duration : this._emissionTime;
|
||
}
|
||
get shape() {
|
||
return this._shape;
|
||
}
|
||
set shape(value) {
|
||
if (this._shape !== value) {
|
||
if (value && value.enable)
|
||
this._owner._render._shaderValues.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SHAPE);
|
||
else
|
||
this._owner._render._shaderValues.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SHAPE);
|
||
this._shape = value;
|
||
}
|
||
}
|
||
get isAlive() {
|
||
if (this._isPlaying || this.aliveParticleCount > 0)
|
||
return true;
|
||
return false;
|
||
}
|
||
get isEmitting() {
|
||
return this._isEmitting;
|
||
}
|
||
get isPlaying() {
|
||
return this._isPlaying;
|
||
}
|
||
get isPaused() {
|
||
return this._isPaused;
|
||
}
|
||
get startLifetimeType() {
|
||
return this._startLifetimeType;
|
||
}
|
||
set startLifetimeType(value) {
|
||
var i, n;
|
||
switch (this.startLifetimeType) {
|
||
case 0:
|
||
this._maxStartLifetime = this.startLifetimeConstant;
|
||
break;
|
||
case 1:
|
||
this._maxStartLifetime = -Number.MAX_VALUE;
|
||
var startLifeTimeGradient = startLifeTimeGradient;
|
||
for (i = 0, n = startLifeTimeGradient.gradientCount; i < n; i++)
|
||
this._maxStartLifetime = Math.max(this._maxStartLifetime, startLifeTimeGradient.getValueByIndex(i));
|
||
break;
|
||
case 2:
|
||
this._maxStartLifetime = Math.max(this.startLifetimeConstantMin, this.startLifetimeConstantMax);
|
||
break;
|
||
case 3:
|
||
this._maxStartLifetime = -Number.MAX_VALUE;
|
||
var startLifeTimeGradientMin = startLifeTimeGradientMin;
|
||
for (i = 0, n = startLifeTimeGradientMin.gradientCount; i < n; i++)
|
||
this._maxStartLifetime = Math.max(this._maxStartLifetime, startLifeTimeGradientMin.getValueByIndex(i));
|
||
var startLifeTimeGradientMax = startLifeTimeGradientMax;
|
||
for (i = 0, n = startLifeTimeGradientMax.gradientCount; i < n; i++)
|
||
this._maxStartLifetime = Math.max(this._maxStartLifetime, startLifeTimeGradientMax.getValueByIndex(i));
|
||
break;
|
||
}
|
||
this._startLifetimeType = value;
|
||
}
|
||
get startLifetimeConstant() {
|
||
return this._startLifetimeConstant;
|
||
}
|
||
set startLifetimeConstant(value) {
|
||
if (this._startLifetimeType === 0)
|
||
this._maxStartLifetime = value;
|
||
this._startLifetimeConstant = value;
|
||
}
|
||
get startLifeTimeGradient() {
|
||
return this._startLifeTimeGradient;
|
||
}
|
||
set startLifeTimeGradient(value) {
|
||
if (this._startLifetimeType === 1) {
|
||
this._maxStartLifetime = -Number.MAX_VALUE;
|
||
for (var i = 0, n = value.gradientCount; i < n; i++)
|
||
this._maxStartLifetime = Math.max(this._maxStartLifetime, value.getValueByIndex(i));
|
||
}
|
||
this._startLifeTimeGradient = value;
|
||
}
|
||
get startLifetimeConstantMin() {
|
||
return this._startLifetimeConstantMin;
|
||
}
|
||
set startLifetimeConstantMin(value) {
|
||
if (this._startLifetimeType === 2)
|
||
this._maxStartLifetime = Math.max(value, this._startLifetimeConstantMax);
|
||
this._startLifetimeConstantMin = value;
|
||
}
|
||
get startLifetimeConstantMax() {
|
||
return this._startLifetimeConstantMax;
|
||
}
|
||
set startLifetimeConstantMax(value) {
|
||
if (this._startLifetimeType === 2)
|
||
this._maxStartLifetime = Math.max(this._startLifetimeConstantMin, value);
|
||
this._startLifetimeConstantMax = value;
|
||
}
|
||
get startLifeTimeGradientMin() {
|
||
return this._startLifeTimeGradientMin;
|
||
}
|
||
set startLifeTimeGradientMin(value) {
|
||
if (this._startLifetimeType === 3) {
|
||
var i, n;
|
||
this._maxStartLifetime = -Number.MAX_VALUE;
|
||
for (i = 0, n = value.gradientCount; i < n; i++)
|
||
this._maxStartLifetime = Math.max(this._maxStartLifetime, value.getValueByIndex(i));
|
||
for (i = 0, n = this._startLifeTimeGradientMax.gradientCount; i < n; i++)
|
||
this._maxStartLifetime = Math.max(this._maxStartLifetime, this._startLifeTimeGradientMax.getValueByIndex(i));
|
||
}
|
||
this._startLifeTimeGradientMin = value;
|
||
}
|
||
get startLifeTimeGradientMax() {
|
||
return this._startLifeTimeGradientMax;
|
||
}
|
||
set startLifeTimeGradientMax(value) {
|
||
if (this._startLifetimeType === 3) {
|
||
var i, n;
|
||
this._maxStartLifetime = -Number.MAX_VALUE;
|
||
for (i = 0, n = this._startLifeTimeGradientMin.gradientCount; i < n; i++)
|
||
this._maxStartLifetime = Math.max(this._maxStartLifetime, this._startLifeTimeGradientMin.getValueByIndex(i));
|
||
for (i = 0, n = value.gradientCount; i < n; i++)
|
||
this._maxStartLifetime = Math.max(this._maxStartLifetime, value.getValueByIndex(i));
|
||
}
|
||
this._startLifeTimeGradientMax = value;
|
||
}
|
||
get velocityOverLifetime() {
|
||
return this._velocityOverLifetime;
|
||
}
|
||
set velocityOverLifetime(value) {
|
||
var shaDat = this._owner._render._shaderValues;
|
||
if (value) {
|
||
var velocity = value.velocity;
|
||
var velocityType = velocity.type;
|
||
if (value.enable) {
|
||
switch (velocityType) {
|
||
case 0:
|
||
shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMECONSTANT);
|
||
break;
|
||
case 1:
|
||
shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMECURVE);
|
||
break;
|
||
case 2:
|
||
shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMERANDOMCONSTANT);
|
||
break;
|
||
case 3:
|
||
shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMERANDOMCURVE);
|
||
break;
|
||
}
|
||
}
|
||
else {
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMECONSTANT);
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMECURVE);
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMERANDOMCONSTANT);
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMERANDOMCURVE);
|
||
}
|
||
switch (velocityType) {
|
||
case 0:
|
||
shaDat.setVector3(ShuriKenParticle3DShaderDeclaration.VOLVELOCITYCONST, velocity.constant);
|
||
break;
|
||
case 1:
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTX, velocity.gradientX._elements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTY, velocity.gradientY._elements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTZ, velocity.gradientZ._elements);
|
||
break;
|
||
case 2:
|
||
shaDat.setVector3(ShuriKenParticle3DShaderDeclaration.VOLVELOCITYCONST, velocity.constantMin);
|
||
shaDat.setVector3(ShuriKenParticle3DShaderDeclaration.VOLVELOCITYCONSTMAX, velocity.constantMax);
|
||
break;
|
||
case 3:
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTX, velocity.gradientXMin._elements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTXMAX, velocity.gradientXMax._elements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTY, velocity.gradientYMin._elements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTYMAX, velocity.gradientYMax._elements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTZ, velocity.gradientZMin._elements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.VOLVELOCITYGRADIENTZMAX, velocity.gradientZMax._elements);
|
||
break;
|
||
}
|
||
shaDat.setInt(ShuriKenParticle3DShaderDeclaration.VOLSPACETYPE, value.space);
|
||
}
|
||
else {
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMECONSTANT);
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMECURVE);
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMERANDOMCONSTANT);
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMERANDOMCURVE);
|
||
}
|
||
this._velocityOverLifetime = value;
|
||
}
|
||
get colorOverLifetime() {
|
||
return this._colorOverLifetime;
|
||
}
|
||
set colorOverLifetime(value) {
|
||
var shaDat = this._owner._render._shaderValues;
|
||
if (value) {
|
||
var color = value.color;
|
||
if (value.enable) {
|
||
switch (color.type) {
|
||
case 1:
|
||
shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_COLOROVERLIFETIME);
|
||
break;
|
||
case 3:
|
||
shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RANDOMCOLOROVERLIFETIME);
|
||
break;
|
||
}
|
||
}
|
||
else {
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_COLOROVERLIFETIME);
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RANDOMCOLOROVERLIFETIME);
|
||
}
|
||
switch (color.type) {
|
||
case 1:
|
||
var gradientColor = color.gradient;
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.COLOROVERLIFEGRADIENTALPHAS, gradientColor._alphaElements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.COLOROVERLIFEGRADIENTCOLORS, gradientColor._rgbElements);
|
||
break;
|
||
case 3:
|
||
var minGradientColor = color.gradientMin;
|
||
var maxGradientColor = color.gradientMax;
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.COLOROVERLIFEGRADIENTALPHAS, minGradientColor._alphaElements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.COLOROVERLIFEGRADIENTCOLORS, minGradientColor._rgbElements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.MAXCOLOROVERLIFEGRADIENTALPHAS, maxGradientColor._alphaElements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.MAXCOLOROVERLIFEGRADIENTCOLORS, maxGradientColor._rgbElements);
|
||
break;
|
||
}
|
||
}
|
||
else {
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_COLOROVERLIFETIME);
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RANDOMCOLOROVERLIFETIME);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.COLOROVERLIFEGRADIENTALPHAS, gradientColor._alphaElements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.COLOROVERLIFEGRADIENTCOLORS, gradientColor._rgbElements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.COLOROVERLIFEGRADIENTALPHAS, minGradientColor._alphaElements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.COLOROVERLIFEGRADIENTCOLORS, minGradientColor._rgbElements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.MAXCOLOROVERLIFEGRADIENTALPHAS, maxGradientColor._alphaElements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.MAXCOLOROVERLIFEGRADIENTCOLORS, maxGradientColor._rgbElements);
|
||
}
|
||
this._colorOverLifetime = value;
|
||
}
|
||
get sizeOverLifetime() {
|
||
return this._sizeOverLifetime;
|
||
}
|
||
set sizeOverLifetime(value) {
|
||
var shaDat = this._owner._render._shaderValues;
|
||
if (value) {
|
||
var size = value.size;
|
||
var sizeSeparate = size.separateAxes;
|
||
var sizeType = size.type;
|
||
if (value.enable) {
|
||
switch (sizeType) {
|
||
case 0:
|
||
if (sizeSeparate)
|
||
shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMECURVESEPERATE);
|
||
else
|
||
shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMECURVE);
|
||
break;
|
||
case 2:
|
||
if (sizeSeparate)
|
||
shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMERANDOMCURVESSEPERATE);
|
||
else
|
||
shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMERANDOMCURVES);
|
||
break;
|
||
}
|
||
}
|
||
else {
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMECURVE);
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMECURVESEPERATE);
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMERANDOMCURVES);
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMERANDOMCURVESSEPERATE);
|
||
}
|
||
switch (sizeType) {
|
||
case 0:
|
||
if (sizeSeparate) {
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.SOLSIZEGRADIENTX, size.gradientX._elements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.SOLSIZEGRADIENTY, size.gradientY._elements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.SOLSizeGradientZ, size.gradientZ._elements);
|
||
}
|
||
else {
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.SOLSIZEGRADIENT, size.gradient._elements);
|
||
}
|
||
break;
|
||
case 2:
|
||
if (sizeSeparate) {
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.SOLSIZEGRADIENTX, size.gradientXMin._elements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.SOLSIZEGRADIENTXMAX, size.gradientXMax._elements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.SOLSIZEGRADIENTY, size.gradientYMin._elements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.SOLSIZEGRADIENTYMAX, size.gradientYMax._elements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.SOLSizeGradientZ, size.gradientZMin._elements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.SOLSizeGradientZMAX, size.gradientZMax._elements);
|
||
}
|
||
else {
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.SOLSIZEGRADIENT, size.gradientMin._elements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.SOLSizeGradientMax, size.gradientMax._elements);
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
else {
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMECURVE);
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMECURVESEPERATE);
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMERANDOMCURVES);
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMERANDOMCURVESSEPERATE);
|
||
}
|
||
this._sizeOverLifetime = value;
|
||
}
|
||
get rotationOverLifetime() {
|
||
return this._rotationOverLifetime;
|
||
}
|
||
set rotationOverLifetime(value) {
|
||
var shaDat = this._owner._render._shaderValues;
|
||
if (value) {
|
||
var rotation = value.angularVelocity;
|
||
if (!rotation)
|
||
return;
|
||
var rotationSeparate = rotation.separateAxes;
|
||
var rotationType = rotation.type;
|
||
if (value.enable) {
|
||
if (rotationSeparate)
|
||
shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMESEPERATE);
|
||
else
|
||
shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIME);
|
||
switch (rotationType) {
|
||
case 0:
|
||
shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMECONSTANT);
|
||
break;
|
||
case 1:
|
||
shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMECURVE);
|
||
break;
|
||
case 2:
|
||
shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMERANDOMCONSTANTS);
|
||
break;
|
||
case 3:
|
||
shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMERANDOMCURVES);
|
||
break;
|
||
}
|
||
}
|
||
else {
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIME);
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMESEPERATE);
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMECONSTANT);
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMECURVE);
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMERANDOMCONSTANTS);
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMERANDOMCURVES);
|
||
}
|
||
switch (rotationType) {
|
||
case 0:
|
||
if (rotationSeparate) {
|
||
shaDat.setVector3(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYCONSTSEPRARATE, rotation.constantSeparate);
|
||
}
|
||
else {
|
||
shaDat.setNumber(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYCONST, rotation.constant);
|
||
}
|
||
break;
|
||
case 1:
|
||
if (rotationSeparate) {
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTX, rotation.gradientX._elements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTY, rotation.gradientY._elements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTZ, rotation.gradientZ._elements);
|
||
}
|
||
else {
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENT, rotation.gradient._elements);
|
||
}
|
||
break;
|
||
case 2:
|
||
if (rotationSeparate) {
|
||
shaDat.setVector3(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYCONSTSEPRARATE, rotation.constantMinSeparate);
|
||
shaDat.setVector3(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYCONSTMAXSEPRARATE, rotation.constantMaxSeparate);
|
||
}
|
||
else {
|
||
shaDat.setNumber(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYCONST, rotation.constantMin);
|
||
shaDat.setNumber(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYCONSTMAX, rotation.constantMax);
|
||
}
|
||
break;
|
||
case 3:
|
||
if (rotationSeparate) {
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTX, rotation.gradientXMin._elements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTXMAX, rotation.gradientXMax._elements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTY, rotation.gradientYMin._elements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTYMAX, rotation.gradientYMax._elements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTZ, rotation.gradientZMin._elements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTZMAX, rotation.gradientZMax._elements);
|
||
}
|
||
else {
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENT, rotation.gradientMin._elements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.ROLANGULARVELOCITYGRADIENTMAX, rotation.gradientMax._elements);
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
else {
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIME);
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMESEPERATE);
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMECONSTANT);
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMECURVE);
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMERANDOMCONSTANTS);
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMERANDOMCURVES);
|
||
}
|
||
this._rotationOverLifetime = value;
|
||
}
|
||
get textureSheetAnimation() {
|
||
return this._textureSheetAnimation;
|
||
}
|
||
set textureSheetAnimation(value) {
|
||
var shaDat = this._owner._render._shaderValues;
|
||
if (value) {
|
||
var frameOverTime = value.frame;
|
||
var textureAniType = frameOverTime.type;
|
||
if (value.enable) {
|
||
switch (textureAniType) {
|
||
case 1:
|
||
shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_TEXTURESHEETANIMATIONCURVE);
|
||
break;
|
||
case 3:
|
||
shaDat.addDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_TEXTURESHEETANIMATIONRANDOMCURVE);
|
||
break;
|
||
}
|
||
}
|
||
else {
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_TEXTURESHEETANIMATIONCURVE);
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_TEXTURESHEETANIMATIONRANDOMCURVE);
|
||
}
|
||
if (textureAniType === 1 || textureAniType === 3) {
|
||
shaDat.setNumber(ShuriKenParticle3DShaderDeclaration.TEXTURESHEETANIMATIONCYCLES, value.cycles);
|
||
var title = value.tiles;
|
||
var _uvLengthE = this._uvLength;
|
||
_uvLengthE.x = 1.0 / title.x;
|
||
_uvLengthE.y = 1.0 / title.y;
|
||
shaDat.setVector2(ShuriKenParticle3DShaderDeclaration.TEXTURESHEETANIMATIONSUBUVLENGTH, this._uvLength);
|
||
}
|
||
switch (textureAniType) {
|
||
case 1:
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.TEXTURESHEETANIMATIONGRADIENTUVS, frameOverTime.frameOverTimeData._elements);
|
||
break;
|
||
case 3:
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.TEXTURESHEETANIMATIONGRADIENTUVS, frameOverTime.frameOverTimeDataMin._elements);
|
||
shaDat.setBuffer(ShuriKenParticle3DShaderDeclaration.TEXTURESHEETANIMATIONGRADIENTMAXUVS, frameOverTime.frameOverTimeDataMax._elements);
|
||
break;
|
||
}
|
||
}
|
||
else {
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_TEXTURESHEETANIMATIONCURVE);
|
||
shaDat.removeDefine(ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_TEXTURESHEETANIMATIONRANDOMCURVE);
|
||
}
|
||
this._textureSheetAnimation = value;
|
||
}
|
||
_getVertexBuffer(index = 0) {
|
||
if (index === 0)
|
||
return this._vertexBuffer;
|
||
else
|
||
return null;
|
||
}
|
||
_getIndexBuffer() {
|
||
return this._indexBuffer;
|
||
}
|
||
_generateBoundingSphere() {
|
||
var centerE = this._boundingSphere.center;
|
||
centerE.x = 0;
|
||
centerE.y = 0;
|
||
centerE.z = 0;
|
||
this._boundingSphere.radius = Number.MAX_VALUE;
|
||
}
|
||
_generateBounds() {
|
||
var particle = this._owner;
|
||
var particleRender = particle.particleRenderer;
|
||
var boundsMin = this._bounds.getMin();
|
||
var boundsMax = this._bounds.getMax();
|
||
var time = 0;
|
||
switch (this.startLifetimeType) {
|
||
case 0:
|
||
time = this._startLifetimeConstant;
|
||
break;
|
||
case 2:
|
||
time = this._startLifetimeConstantMax;
|
||
break;
|
||
}
|
||
var speedOrigan = 0;
|
||
switch (this.startSpeedType) {
|
||
case 0:
|
||
speedOrigan = this.startSpeedConstant;
|
||
break;
|
||
case 2:
|
||
speedOrigan = this.startSpeedConstantMax;
|
||
break;
|
||
}
|
||
var maxSizeScale = 0;
|
||
if (this.threeDStartSize) {
|
||
switch (this.startSizeType) {
|
||
case 0:
|
||
maxSizeScale = Math.max(this.startSizeConstantSeparate.x, this.startSizeConstantSeparate.y, this.startSizeConstantSeparate.z);
|
||
break;
|
||
case 2:
|
||
maxSizeScale = Math.max(this.startSizeConstantMaxSeparate.x, this.startSizeConstantMaxSeparate.y, this.startSizeConstantMaxSeparate.z);
|
||
break;
|
||
}
|
||
}
|
||
else {
|
||
switch (this.startSizeType) {
|
||
case 0:
|
||
maxSizeScale = this.startSizeConstant;
|
||
break;
|
||
case 2:
|
||
maxSizeScale = this.startSizeConstantMax;
|
||
break;
|
||
}
|
||
}
|
||
var zDirectionSpeed = ShurikenParticleSystem._tempVector30;
|
||
var fDirectionSpeed = ShurikenParticleSystem._tempVector31;
|
||
var zEmisionOffsetXYZ = ShurikenParticleSystem._tempVector32;
|
||
var fEmisionOffsetXYZ = ShurikenParticleSystem._tempVector33;
|
||
zDirectionSpeed.setValue(0, 0, 1);
|
||
fDirectionSpeed.setValue(0, 0, 0);
|
||
zEmisionOffsetXYZ.setValue(0, 0, 0);
|
||
fEmisionOffsetXYZ.setValue(0, 0, 0);
|
||
if (this.shape && this.shape.enable) {
|
||
switch (this.shape.shapeType) {
|
||
case exports.ParticleSystemShapeType.Sphere:
|
||
var sphere = this.shape;
|
||
zDirectionSpeed.setValue(1, 1, 1);
|
||
fDirectionSpeed.setValue(1, 1, 1);
|
||
zEmisionOffsetXYZ.setValue(sphere.radius, sphere.radius, sphere.radius);
|
||
fEmisionOffsetXYZ.setValue(sphere.radius, sphere.radius, sphere.radius);
|
||
break;
|
||
case exports.ParticleSystemShapeType.Hemisphere:
|
||
var hemiShpere = this.shape;
|
||
zDirectionSpeed.setValue(1, 1, 1);
|
||
fDirectionSpeed.setValue(1, 1, 1);
|
||
zEmisionOffsetXYZ.setValue(hemiShpere.radius, hemiShpere.radius, hemiShpere.radius);
|
||
fEmisionOffsetXYZ.setValue(hemiShpere.radius, hemiShpere.radius, 0.0);
|
||
break;
|
||
case exports.ParticleSystemShapeType.Cone:
|
||
var cone = this.shape;
|
||
if (cone.emitType == 0 || cone.emitType == 1) {
|
||
var angle = cone.angle;
|
||
var sinAngle = Math.sin(angle);
|
||
zDirectionSpeed.setValue(sinAngle, sinAngle, 1.0);
|
||
fDirectionSpeed.setValue(sinAngle, sinAngle, 0.0);
|
||
zEmisionOffsetXYZ.setValue(cone.radius, cone.radius, 0.0);
|
||
fEmisionOffsetXYZ.setValue(cone.radius, cone.radius, 0.0);
|
||
break;
|
||
}
|
||
else if (cone.emitType == 2 || cone.emitType == 3) {
|
||
var angle = cone.angle;
|
||
var sinAngle = Math.sin(angle);
|
||
var coneLength = cone.length;
|
||
zDirectionSpeed.setValue(sinAngle, sinAngle, 1.0);
|
||
fDirectionSpeed.setValue(sinAngle, sinAngle, 0.0);
|
||
var tanAngle = Math.tan(angle);
|
||
var rPLCT = cone.radius + coneLength * tanAngle;
|
||
zEmisionOffsetXYZ.setValue(rPLCT, rPLCT, coneLength);
|
||
fEmisionOffsetXYZ.setValue(rPLCT, rPLCT, 0.0);
|
||
}
|
||
break;
|
||
case exports.ParticleSystemShapeType.Box:
|
||
var box = this.shape;
|
||
if (this.shape.randomDirection != 0) {
|
||
zDirectionSpeed.setValue(1, 1, 1);
|
||
fDirectionSpeed.setValue(1, 1, 1);
|
||
}
|
||
zEmisionOffsetXYZ.setValue(box.x / 2, box.y / 2, box.z / 2);
|
||
fEmisionOffsetXYZ.setValue(box.x / 2, box.y / 2, box.z / 2);
|
||
break;
|
||
case exports.ParticleSystemShapeType.Circle:
|
||
var circle = this.shape;
|
||
zDirectionSpeed.setValue(1, 1, 1);
|
||
fDirectionSpeed.setValue(1, 1, 1);
|
||
zEmisionOffsetXYZ.setValue(circle.radius, circle.radius, 0);
|
||
fEmisionOffsetXYZ.setValue(circle.radius, circle.radius, 0);
|
||
break;
|
||
}
|
||
}
|
||
var meshSize = 0;
|
||
var meshMode = particleRender.renderMode == 4;
|
||
switch (particleRender.renderMode) {
|
||
case 0:
|
||
case 1:
|
||
case 2:
|
||
case 3:
|
||
meshSize = ShurikenParticleSystem.halfKSqrtOf2;
|
||
break;
|
||
case 4:
|
||
var meshBounds = particleRender.mesh.bounds;
|
||
meshSize = Math.sqrt(Math.pow(meshBounds.getExtent().x, 2.0) + Math.pow(meshBounds.getExtent().y, 2.0) + Math.pow(meshBounds.getExtent().z, 2.0));
|
||
break;
|
||
}
|
||
var endSizeOffset = ShurikenParticleSystem._tempVector36;
|
||
endSizeOffset.setValue(1, 1, 1);
|
||
if (this.sizeOverLifetime && this.sizeOverLifetime.enable) {
|
||
var gradientSize = this.sizeOverLifetime.size;
|
||
var maxSize = gradientSize.getMaxSizeInGradient(meshMode);
|
||
endSizeOffset.setValue(maxSize, maxSize, maxSize);
|
||
}
|
||
var offsetSize = meshSize * maxSizeScale;
|
||
Vector3.scale(endSizeOffset, offsetSize, endSizeOffset);
|
||
var speedZOffset = ShurikenParticleSystem._tempVector34;
|
||
var speedFOffset = ShurikenParticleSystem._tempVector35;
|
||
if (speedOrigan > 0) {
|
||
Vector3.scale(zDirectionSpeed, speedOrigan, speedZOffset);
|
||
Vector3.scale(fDirectionSpeed, speedOrigan, speedFOffset);
|
||
}
|
||
else {
|
||
Vector3.scale(zDirectionSpeed, -speedOrigan, speedFOffset);
|
||
Vector3.scale(fDirectionSpeed, -speedOrigan, speedZOffset);
|
||
}
|
||
if (this.velocityOverLifetime && this.velocityOverLifetime.enable) {
|
||
var gradientVelocity = this.velocityOverLifetime.velocity;
|
||
var velocitySpeedOffset = ShurikenParticleSystem._tempVector37;
|
||
velocitySpeedOffset.setValue(0, 0, 0);
|
||
switch (gradientVelocity.type) {
|
||
case 0:
|
||
gradientVelocity.constant.cloneTo(velocitySpeedOffset);
|
||
break;
|
||
case 2:
|
||
gradientVelocity.constantMax.cloneTo(velocitySpeedOffset);
|
||
break;
|
||
case 1:
|
||
var curveX = gradientVelocity.gradientX.getAverageValue();
|
||
var curveY = gradientVelocity.gradientY.getAverageValue();
|
||
var curveZ = gradientVelocity.gradientZ.getAverageValue();
|
||
velocitySpeedOffset.setValue(curveX, curveY, curveZ);
|
||
break;
|
||
case 3:
|
||
var xMax = gradientVelocity.gradientXMax.getAverageValue();
|
||
var yMax = gradientVelocity.gradientYMax.getAverageValue();
|
||
var zMax = gradientVelocity.gradientZMax.getAverageValue();
|
||
velocitySpeedOffset.setValue(xMax, yMax, zMax);
|
||
break;
|
||
}
|
||
if (this.velocityOverLifetime.space == 1) {
|
||
Vector3.transformV3ToV3(velocitySpeedOffset, this._owner.transform.worldMatrix, velocitySpeedOffset);
|
||
}
|
||
Vector3.add(speedZOffset, velocitySpeedOffset, speedZOffset);
|
||
Vector3.subtract(speedFOffset, velocitySpeedOffset, speedFOffset);
|
||
Vector3.max(speedZOffset, Vector3._ZERO, speedZOffset);
|
||
Vector3.max(speedFOffset, Vector3._ZERO, speedFOffset);
|
||
}
|
||
Vector3.scale(speedZOffset, time, speedZOffset);
|
||
Vector3.scale(speedFOffset, time, speedFOffset);
|
||
var gravity = this.gravityModifier;
|
||
if (gravity != 0) {
|
||
var gravityOffset = 0.5 * ShurikenParticleSystem.g * gravity * time * time;
|
||
var speedZOffsetY = speedZOffset.y - gravityOffset;
|
||
var speedFOffsetY = speedFOffset.y + gravityOffset;
|
||
speedZOffsetY = speedZOffsetY > 0 ? speedZOffsetY : 0;
|
||
speedFOffsetY = speedFOffsetY > 0 ? speedFOffsetY : 0;
|
||
this._gravityOffset.setValue(speedZOffset.y - speedZOffsetY, speedFOffsetY - speedFOffset.y);
|
||
}
|
||
Vector3.add(speedZOffset, endSizeOffset, boundsMax);
|
||
Vector3.add(boundsMax, zEmisionOffsetXYZ, boundsMax);
|
||
Vector3.add(speedFOffset, endSizeOffset, boundsMin);
|
||
Vector3.add(boundsMin, fEmisionOffsetXYZ, boundsMin);
|
||
Vector3.scale(boundsMin, -1, boundsMin);
|
||
this._bounds.setMin(boundsMin);
|
||
this._bounds.setMax(boundsMax);
|
||
}
|
||
get customBounds() {
|
||
return this._customBounds;
|
||
}
|
||
set customBounds(value) {
|
||
if (value) {
|
||
this._useCustomBounds = true;
|
||
}
|
||
else {
|
||
this._useCustomBounds = false;
|
||
}
|
||
this._customBounds = value;
|
||
}
|
||
_simulationSupported() {
|
||
if (this.simulationSpace == 0) {
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
_updateEmission() {
|
||
if (!this.isAlive)
|
||
return;
|
||
if (this._simulateUpdate) {
|
||
this._simulateUpdate = false;
|
||
}
|
||
else {
|
||
var elapsedTime = (this._startUpdateLoopCount !== Laya.Stat.loopCount && !this._isPaused) ? this._owner._scene.timer._delta / 1000.0 : 0;
|
||
elapsedTime = Math.min(ShurikenParticleSystem._maxElapsedTime, elapsedTime * this.simulationSpeed);
|
||
this._updateParticles(elapsedTime);
|
||
}
|
||
}
|
||
_updateParticles(elapsedTime) {
|
||
if (this._ownerRender.renderMode === 4 && !this._ownerRender.mesh)
|
||
return;
|
||
this._currentTime += elapsedTime;
|
||
this._retireActiveParticles();
|
||
this._freeRetiredParticles();
|
||
this._totalDelayTime += elapsedTime;
|
||
if (this._totalDelayTime < this._playStartDelay) {
|
||
return;
|
||
}
|
||
if (this._emission.enable && this._isEmitting && !this._isPaused)
|
||
this._advanceTime(elapsedTime, this._currentTime);
|
||
}
|
||
_updateParticlesSimulationRestart(time) {
|
||
this._firstActiveElement = 0;
|
||
this._firstNewElement = 0;
|
||
this._firstFreeElement = 0;
|
||
this._firstRetiredElement = 0;
|
||
this._burstsIndex = 0;
|
||
this._frameRateTime = time;
|
||
this._emissionTime = 0;
|
||
this._totalDelayTime = 0;
|
||
this._currentTime = time;
|
||
var delayTime = time;
|
||
if (delayTime < this._playStartDelay) {
|
||
this._totalDelayTime = delayTime;
|
||
return;
|
||
}
|
||
if (this._emission.enable)
|
||
this._advanceTime(time, time);
|
||
}
|
||
_retireActiveParticles() {
|
||
const epsilon = 0.0001;
|
||
while (this._firstActiveElement != this._firstNewElement) {
|
||
var index = this._firstActiveElement * this._floatCountPerVertex * this._vertexStride;
|
||
var timeIndex = index + this._timeIndex;
|
||
var particleAge = this._currentTime - this._vertices[timeIndex];
|
||
if (particleAge + epsilon < this._vertices[index + this._startLifeTimeIndex])
|
||
break;
|
||
this._vertices[timeIndex] = this._drawCounter;
|
||
this._firstActiveElement++;
|
||
if (this._firstActiveElement >= this._bufferMaxParticles)
|
||
this._firstActiveElement = 0;
|
||
}
|
||
}
|
||
_freeRetiredParticles() {
|
||
while (this._firstRetiredElement != this._firstActiveElement) {
|
||
var age = this._drawCounter - this._vertices[this._firstRetiredElement * this._floatCountPerVertex * this._vertexStride + this._timeIndex];
|
||
this._firstRetiredElement++;
|
||
if (this._firstRetiredElement >= this._bufferMaxParticles)
|
||
this._firstRetiredElement = 0;
|
||
}
|
||
}
|
||
_burst(fromTime, toTime) {
|
||
var totalEmitCount = 0;
|
||
var bursts = this._emission._bursts;
|
||
for (var n = bursts.length; this._burstsIndex < n; this._burstsIndex++) {
|
||
var burst = bursts[this._burstsIndex];
|
||
var burstTime = burst.time;
|
||
if (fromTime <= burstTime && burstTime < toTime) {
|
||
var emitCount;
|
||
if (this.autoRandomSeed) {
|
||
emitCount = Laya.MathUtil.lerp(burst.minCount, burst.maxCount, Math.random());
|
||
}
|
||
else {
|
||
this._rand.seed = this._randomSeeds[0];
|
||
emitCount = Laya.MathUtil.lerp(burst.minCount, burst.maxCount, this._rand.getFloat());
|
||
this._randomSeeds[0] = this._rand.seed;
|
||
}
|
||
totalEmitCount += emitCount;
|
||
}
|
||
else {
|
||
break;
|
||
}
|
||
}
|
||
return totalEmitCount;
|
||
}
|
||
_advanceTime(elapsedTime, emitTime) {
|
||
var i;
|
||
var lastEmissionTime = this._emissionTime;
|
||
this._emissionTime += elapsedTime;
|
||
var totalEmitCount = 0;
|
||
if (this._emissionTime > this.duration) {
|
||
if (this.looping) {
|
||
totalEmitCount += this._burst(lastEmissionTime, this._emissionTime);
|
||
this._emissionTime -= this.duration;
|
||
this._burstsIndex = 0;
|
||
totalEmitCount += this._burst(0, this._emissionTime);
|
||
}
|
||
else {
|
||
totalEmitCount = Math.min(this.maxParticles - this.aliveParticleCount, totalEmitCount);
|
||
for (i = 0; i < totalEmitCount; i++)
|
||
this.emit(emitTime);
|
||
this._isPlaying = false;
|
||
this.stop();
|
||
return;
|
||
}
|
||
}
|
||
else {
|
||
totalEmitCount += this._burst(lastEmissionTime, this._emissionTime);
|
||
}
|
||
totalEmitCount = Math.min(this.maxParticles - this.aliveParticleCount, totalEmitCount);
|
||
for (i = 0; i < totalEmitCount; i++)
|
||
this.emit(emitTime);
|
||
var emissionRate = this.emission.emissionRate;
|
||
if (emissionRate > 0) {
|
||
var minEmissionTime = 1 / emissionRate;
|
||
this._frameRateTime += minEmissionTime;
|
||
this._frameRateTime = this._currentTime - (this._currentTime - this._frameRateTime) % this._maxStartLifetime;
|
||
while (this._frameRateTime <= emitTime) {
|
||
if (this.emit(this._frameRateTime))
|
||
this._frameRateTime += minEmissionTime;
|
||
else
|
||
break;
|
||
}
|
||
this._frameRateTime = Math.floor(emitTime / minEmissionTime) * minEmissionTime;
|
||
}
|
||
}
|
||
_initBufferDatas() {
|
||
if (this._vertexBuffer) {
|
||
var memorySize = this._vertexBuffer._byteLength + this._indexBuffer.indexCount * 2;
|
||
this._vertexBuffer.destroy();
|
||
this._indexBuffer.destroy();
|
||
Laya.Resource._addMemory(-memorySize, -memorySize);
|
||
}
|
||
var gl = Laya.LayaGL.instance;
|
||
var render = this._ownerRender;
|
||
var renderMode = render.renderMode;
|
||
if (renderMode !== -1 && this.maxParticles > 0) {
|
||
var indices, i, j, m, indexOffset, perPartOffset, vertexDeclaration;
|
||
var vbMemorySize = 0, memorySize = 0;
|
||
var mesh = render.mesh;
|
||
if (renderMode === 4) {
|
||
if (mesh) {
|
||
vertexDeclaration = VertexShurikenParticleMesh.vertexDeclaration;
|
||
this._floatCountPerVertex = vertexDeclaration.vertexStride / 4;
|
||
this._startLifeTimeIndex = 12;
|
||
this._timeIndex = 16;
|
||
this._vertexStride = mesh._vertexCount;
|
||
var totalVertexCount = this._bufferMaxParticles * this._vertexStride;
|
||
var vbCount = Math.floor(totalVertexCount / 65535) + 1;
|
||
var lastVBVertexCount = totalVertexCount % 65535;
|
||
if (vbCount > 1) {
|
||
throw new Error("ShurikenParticleSystem:the maxParticleCount multiply mesh vertexCount is large than 65535.");
|
||
}
|
||
vbMemorySize = vertexDeclaration.vertexStride * lastVBVertexCount;
|
||
this._vertexBuffer = new VertexBuffer3D(vbMemorySize, gl.DYNAMIC_DRAW);
|
||
this._vertexBuffer.vertexDeclaration = vertexDeclaration;
|
||
this._vertices = new Float32Array(this._floatCountPerVertex * lastVBVertexCount);
|
||
this._indexStride = mesh._indexBuffer.indexCount;
|
||
var indexDatas = mesh._indexBuffer.getData();
|
||
var indexCount = this._bufferMaxParticles * this._indexStride;
|
||
this._indexBuffer = new IndexBuffer3D(exports.IndexFormat.UInt16, indexCount, gl.STATIC_DRAW);
|
||
indices = new Uint16Array(indexCount);
|
||
memorySize = vbMemorySize + indexCount * 2;
|
||
indexOffset = 0;
|
||
for (i = 0; i < this._bufferMaxParticles; i++) {
|
||
var indexValueOffset = i * this._vertexStride;
|
||
for (j = 0, m = indexDatas.length; j < m; j++)
|
||
indices[indexOffset++] = indexValueOffset + indexDatas[j];
|
||
}
|
||
this._indexBuffer.setData(indices);
|
||
this._bufferState.bind();
|
||
this._bufferState.applyVertexBuffer(this._vertexBuffer);
|
||
this._bufferState.applyIndexBuffer(this._indexBuffer);
|
||
this._bufferState.unBind();
|
||
}
|
||
}
|
||
else {
|
||
vertexDeclaration = VertexShurikenParticleBillboard.vertexDeclaration;
|
||
this._floatCountPerVertex = vertexDeclaration.vertexStride / 4;
|
||
this._startLifeTimeIndex = 7;
|
||
this._timeIndex = 11;
|
||
this._vertexStride = 4;
|
||
vbMemorySize = vertexDeclaration.vertexStride * this._bufferMaxParticles * this._vertexStride;
|
||
this._vertexBuffer = new VertexBuffer3D(vbMemorySize, gl.DYNAMIC_DRAW);
|
||
this._vertexBuffer.vertexDeclaration = vertexDeclaration;
|
||
this._vertices = new Float32Array(this._floatCountPerVertex * this._bufferMaxParticles * this._vertexStride);
|
||
for (i = 0; i < this._bufferMaxParticles; i++) {
|
||
perPartOffset = i * this._floatCountPerVertex * this._vertexStride;
|
||
this._vertices[perPartOffset] = -0.5;
|
||
this._vertices[perPartOffset + 1] = -0.5;
|
||
this._vertices[perPartOffset + 2] = 0;
|
||
this._vertices[perPartOffset + 3] = 1;
|
||
perPartOffset += this._floatCountPerVertex;
|
||
this._vertices[perPartOffset] = 0.5;
|
||
this._vertices[perPartOffset + 1] = -0.5;
|
||
this._vertices[perPartOffset + 2] = 1;
|
||
this._vertices[perPartOffset + 3] = 1;
|
||
perPartOffset += this._floatCountPerVertex;
|
||
this._vertices[perPartOffset] = 0.5;
|
||
this._vertices[perPartOffset + 1] = 0.5;
|
||
this._vertices[perPartOffset + 2] = 1;
|
||
this._vertices[perPartOffset + 3] = 0;
|
||
perPartOffset += this._floatCountPerVertex;
|
||
this._vertices[perPartOffset] = -0.5;
|
||
this._vertices[perPartOffset + 1] = 0.5;
|
||
this._vertices[perPartOffset + 2] = 0;
|
||
this._vertices[perPartOffset + 3] = 0;
|
||
}
|
||
this._indexStride = 6;
|
||
this._indexBuffer = new IndexBuffer3D(exports.IndexFormat.UInt16, this._bufferMaxParticles * 6, gl.STATIC_DRAW);
|
||
indices = new Uint16Array(this._bufferMaxParticles * 6);
|
||
for (i = 0; i < this._bufferMaxParticles; i++) {
|
||
indexOffset = i * 6;
|
||
var firstVertex = i * this._vertexStride, secondVertex = firstVertex + 2;
|
||
indices[indexOffset++] = firstVertex;
|
||
indices[indexOffset++] = secondVertex;
|
||
indices[indexOffset++] = firstVertex + 1;
|
||
indices[indexOffset++] = firstVertex;
|
||
indices[indexOffset++] = firstVertex + 3;
|
||
indices[indexOffset++] = secondVertex;
|
||
}
|
||
this._indexBuffer.setData(indices);
|
||
memorySize = vbMemorySize + this._bufferMaxParticles * 6 * 2;
|
||
this._bufferState.bind();
|
||
this._bufferState.applyVertexBuffer(this._vertexBuffer);
|
||
this._bufferState.applyIndexBuffer(this._indexBuffer);
|
||
this._bufferState.unBind();
|
||
}
|
||
Laya.Resource._addMemory(memorySize, memorySize);
|
||
}
|
||
}
|
||
destroy() {
|
||
super.destroy();
|
||
if (this._vertexBuffer) {
|
||
var memorySize = this._vertexBuffer._byteLength;
|
||
Laya.Resource._addMemory(-memorySize, -memorySize);
|
||
this._vertexBuffer.destroy();
|
||
this._vertexBuffer = null;
|
||
}
|
||
if (this._indexBuffer) {
|
||
var memorySize = this._indexBuffer._byteLength;
|
||
Laya.Resource._addMemory(-memorySize, -memorySize);
|
||
this._indexBuffer.destroy();
|
||
this._indexBuffer = null;
|
||
}
|
||
this._bufferState.destroy();
|
||
this._emission.destroy();
|
||
this._boundingBox = null;
|
||
this._boundingSphere = null;
|
||
this._boundingBoxCorners = null;
|
||
this._bounds = null;
|
||
this._customBounds = null;
|
||
this._bufferState = null;
|
||
this._owner = null;
|
||
this._vertices = null;
|
||
this._indexBuffer = null;
|
||
this._emission = null;
|
||
this._shape = null;
|
||
this.startLifeTimeGradient = null;
|
||
this.startLifeTimeGradientMin = null;
|
||
this.startLifeTimeGradientMax = null;
|
||
this.startSizeConstantSeparate = null;
|
||
this.startSizeConstantMinSeparate = null;
|
||
this.startSizeConstantMaxSeparate = null;
|
||
this.startRotationConstantSeparate = null;
|
||
this.startRotationConstantMinSeparate = null;
|
||
this.startRotationConstantMaxSeparate = null;
|
||
this.startColorConstant = null;
|
||
this.startColorConstantMin = null;
|
||
this.startColorConstantMax = null;
|
||
this._velocityOverLifetime = null;
|
||
this._colorOverLifetime = null;
|
||
this._sizeOverLifetime = null;
|
||
this._rotationOverLifetime = null;
|
||
this._textureSheetAnimation = null;
|
||
}
|
||
emit(time) {
|
||
var position = ShurikenParticleSystem._tempPosition;
|
||
var direction = ShurikenParticleSystem._tempDirection;
|
||
if (this._shape && this._shape.enable) {
|
||
if (this.autoRandomSeed)
|
||
this._shape.generatePositionAndDirection(position, direction);
|
||
else
|
||
this._shape.generatePositionAndDirection(position, direction, this._rand, this._randomSeeds);
|
||
}
|
||
else {
|
||
position.x = position.y = position.z = 0;
|
||
direction.x = direction.y = 0;
|
||
direction.z = 1;
|
||
}
|
||
return this.addParticle(position, direction, time);
|
||
}
|
||
addParticle(position, direction, time) {
|
||
Vector3.normalize(direction, direction);
|
||
var nextFreeParticle = this._firstFreeElement + 1;
|
||
if (nextFreeParticle >= this._bufferMaxParticles)
|
||
nextFreeParticle = 0;
|
||
if (nextFreeParticle === this._firstRetiredElement)
|
||
return false;
|
||
var transform = this._owner.transform;
|
||
ShurikenParticleData.create(this, this._ownerRender);
|
||
var particleAge = this._currentTime - time;
|
||
if (particleAge >= ShurikenParticleData.startLifeTime)
|
||
return true;
|
||
var pos, rot;
|
||
if (this.simulationSpace == 0) {
|
||
pos = transform.position;
|
||
rot = transform.rotation;
|
||
}
|
||
var startSpeed;
|
||
switch (this.startSpeedType) {
|
||
case 0:
|
||
startSpeed = this.startSpeedConstant;
|
||
break;
|
||
case 2:
|
||
if (this.autoRandomSeed) {
|
||
startSpeed = Laya.MathUtil.lerp(this.startSpeedConstantMin, this.startSpeedConstantMax, Math.random());
|
||
}
|
||
else {
|
||
this._rand.seed = this._randomSeeds[8];
|
||
startSpeed = Laya.MathUtil.lerp(this.startSpeedConstantMin, this.startSpeedConstantMax, this._rand.getFloat());
|
||
this._randomSeeds[8] = this._rand.seed;
|
||
}
|
||
break;
|
||
}
|
||
var randomVelocityX, randomVelocityY, randomVelocityZ, randomColor, randomSize, randomRotation, randomTextureAnimation;
|
||
var needRandomVelocity = this._velocityOverLifetime && this._velocityOverLifetime.enable;
|
||
if (needRandomVelocity) {
|
||
var velocityType = this._velocityOverLifetime.velocity.type;
|
||
if (velocityType === 2 || velocityType === 3) {
|
||
if (this.autoRandomSeed) {
|
||
randomVelocityX = Math.random();
|
||
randomVelocityY = Math.random();
|
||
randomVelocityZ = Math.random();
|
||
}
|
||
else {
|
||
this._rand.seed = this._randomSeeds[9];
|
||
randomVelocityX = this._rand.getFloat();
|
||
randomVelocityY = this._rand.getFloat();
|
||
randomVelocityZ = this._rand.getFloat();
|
||
this._randomSeeds[9] = this._rand.seed;
|
||
}
|
||
}
|
||
else {
|
||
needRandomVelocity = false;
|
||
}
|
||
}
|
||
else {
|
||
needRandomVelocity = false;
|
||
}
|
||
var needRandomColor = this._colorOverLifetime && this._colorOverLifetime.enable;
|
||
if (needRandomColor) {
|
||
var colorType = this._colorOverLifetime.color.type;
|
||
if (colorType === 3) {
|
||
if (this.autoRandomSeed) {
|
||
randomColor = Math.random();
|
||
}
|
||
else {
|
||
this._rand.seed = this._randomSeeds[10];
|
||
randomColor = this._rand.getFloat();
|
||
this._randomSeeds[10] = this._rand.seed;
|
||
}
|
||
}
|
||
else {
|
||
needRandomColor = false;
|
||
}
|
||
}
|
||
else {
|
||
needRandomColor = false;
|
||
}
|
||
var needRandomSize = this._sizeOverLifetime && this._sizeOverLifetime.enable;
|
||
if (needRandomSize) {
|
||
var sizeType = this._sizeOverLifetime.size.type;
|
||
if (sizeType === 3) {
|
||
if (this.autoRandomSeed) {
|
||
randomSize = Math.random();
|
||
}
|
||
else {
|
||
this._rand.seed = this._randomSeeds[11];
|
||
randomSize = this._rand.getFloat();
|
||
this._randomSeeds[11] = this._rand.seed;
|
||
}
|
||
}
|
||
else {
|
||
needRandomSize = false;
|
||
}
|
||
}
|
||
else {
|
||
needRandomSize = false;
|
||
}
|
||
var needRandomRotation = this._rotationOverLifetime && this._rotationOverLifetime.enable;
|
||
if (needRandomRotation) {
|
||
var rotationType = this._rotationOverLifetime.angularVelocity.type;
|
||
if (rotationType === 2 || rotationType === 3) {
|
||
if (this.autoRandomSeed) {
|
||
randomRotation = Math.random();
|
||
}
|
||
else {
|
||
this._rand.seed = this._randomSeeds[12];
|
||
randomRotation = this._rand.getFloat();
|
||
this._randomSeeds[12] = this._rand.seed;
|
||
}
|
||
}
|
||
else {
|
||
needRandomRotation = false;
|
||
}
|
||
}
|
||
else {
|
||
needRandomRotation = false;
|
||
}
|
||
var needRandomTextureAnimation = this._textureSheetAnimation && this._textureSheetAnimation.enable;
|
||
if (needRandomTextureAnimation) {
|
||
var textureAnimationType = this._textureSheetAnimation.frame.type;
|
||
if (textureAnimationType === 3) {
|
||
if (this.autoRandomSeed) {
|
||
randomTextureAnimation = Math.random();
|
||
}
|
||
else {
|
||
this._rand.seed = this._randomSeeds[15];
|
||
randomTextureAnimation = this._rand.getFloat();
|
||
this._randomSeeds[15] = this._rand.seed;
|
||
}
|
||
}
|
||
else {
|
||
needRandomTextureAnimation = false;
|
||
}
|
||
}
|
||
else {
|
||
needRandomTextureAnimation = false;
|
||
}
|
||
var startIndex = this._firstFreeElement * this._floatCountPerVertex * this._vertexStride;
|
||
var subU = ShurikenParticleData.startUVInfo[0];
|
||
var subV = ShurikenParticleData.startUVInfo[1];
|
||
var startU = ShurikenParticleData.startUVInfo[2];
|
||
var startV = ShurikenParticleData.startUVInfo[3];
|
||
var meshVertices, meshVertexStride, meshPosOffset, meshCorOffset, meshUVOffset, meshVertexIndex;
|
||
var render = this._ownerRender;
|
||
if (render.renderMode === 4) {
|
||
var meshVB = render.mesh._vertexBuffer;
|
||
meshVertices = meshVB.getFloat32Data();
|
||
var meshVertexDeclaration = meshVB.vertexDeclaration;
|
||
meshPosOffset = meshVertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_POSITION0)._offset / 4;
|
||
var colorElement = meshVertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_COLOR0);
|
||
meshCorOffset = colorElement ? colorElement._offset / 4 : -1;
|
||
var uvElement = meshVertexDeclaration.getVertexElementByUsage(VertexMesh.MESH_TEXTURECOORDINATE0);
|
||
meshUVOffset = uvElement ? uvElement._offset / 4 : -1;
|
||
meshVertexStride = meshVertexDeclaration.vertexStride / 4;
|
||
meshVertexIndex = 0;
|
||
}
|
||
else {
|
||
this._vertices[startIndex + 2] = startU;
|
||
this._vertices[startIndex + 3] = startV + subV;
|
||
var secondOffset = startIndex + this._floatCountPerVertex;
|
||
this._vertices[secondOffset + 2] = startU + subU;
|
||
this._vertices[secondOffset + 3] = startV + subV;
|
||
var thirdOffset = secondOffset + this._floatCountPerVertex;
|
||
this._vertices[thirdOffset + 2] = startU + subU;
|
||
this._vertices[thirdOffset + 3] = startV;
|
||
var fourthOffset = thirdOffset + this._floatCountPerVertex;
|
||
this._vertices[fourthOffset + 2] = startU;
|
||
this._vertices[fourthOffset + 3] = startV;
|
||
}
|
||
for (var i = startIndex, n = startIndex + this._floatCountPerVertex * this._vertexStride; i < n; i += this._floatCountPerVertex) {
|
||
var offset;
|
||
if (render.renderMode === 4) {
|
||
offset = i;
|
||
var vertexOffset = meshVertexStride * (meshVertexIndex++);
|
||
var meshOffset = vertexOffset + meshPosOffset;
|
||
this._vertices[offset++] = meshVertices[meshOffset++];
|
||
this._vertices[offset++] = meshVertices[meshOffset++];
|
||
this._vertices[offset++] = meshVertices[meshOffset];
|
||
if (meshCorOffset === -1) {
|
||
this._vertices[offset++] = 1.0;
|
||
this._vertices[offset++] = 1.0;
|
||
this._vertices[offset++] = 1.0;
|
||
this._vertices[offset++] = 1.0;
|
||
}
|
||
else {
|
||
meshOffset = vertexOffset + meshCorOffset;
|
||
this._vertices[offset++] = meshVertices[meshOffset++];
|
||
this._vertices[offset++] = meshVertices[meshOffset++];
|
||
this._vertices[offset++] = meshVertices[meshOffset++];
|
||
this._vertices[offset++] = meshVertices[meshOffset];
|
||
}
|
||
if (meshUVOffset === -1) {
|
||
this._vertices[offset++] = 0.0;
|
||
this._vertices[offset++] = 0.0;
|
||
}
|
||
else {
|
||
meshOffset = vertexOffset + meshUVOffset;
|
||
this._vertices[offset++] = startU + meshVertices[meshOffset++] * subU;
|
||
this._vertices[offset++] = startV + meshVertices[meshOffset] * subV;
|
||
}
|
||
}
|
||
else {
|
||
offset = i + 4;
|
||
}
|
||
this._vertices[offset++] = position.x;
|
||
this._vertices[offset++] = position.y;
|
||
this._vertices[offset++] = position.z;
|
||
this._vertices[offset++] = ShurikenParticleData.startLifeTime;
|
||
this._vertices[offset++] = direction.x;
|
||
this._vertices[offset++] = direction.y;
|
||
this._vertices[offset++] = direction.z;
|
||
this._vertices[offset++] = time;
|
||
this._vertices[offset++] = ShurikenParticleData.startColor.x;
|
||
this._vertices[offset++] = ShurikenParticleData.startColor.y;
|
||
this._vertices[offset++] = ShurikenParticleData.startColor.z;
|
||
this._vertices[offset++] = ShurikenParticleData.startColor.w;
|
||
this._vertices[offset++] = ShurikenParticleData.startSize[0];
|
||
this._vertices[offset++] = ShurikenParticleData.startSize[1];
|
||
this._vertices[offset++] = ShurikenParticleData.startSize[2];
|
||
this._vertices[offset++] = ShurikenParticleData.startRotation[0];
|
||
this._vertices[offset++] = ShurikenParticleData.startRotation[1];
|
||
this._vertices[offset++] = ShurikenParticleData.startRotation[2];
|
||
this._vertices[offset++] = startSpeed;
|
||
needRandomColor && (this._vertices[offset + 1] = randomColor);
|
||
needRandomSize && (this._vertices[offset + 2] = randomSize);
|
||
needRandomRotation && (this._vertices[offset + 3] = randomRotation);
|
||
needRandomTextureAnimation && (this._vertices[offset + 4] = randomTextureAnimation);
|
||
if (needRandomVelocity) {
|
||
this._vertices[offset + 5] = randomVelocityX;
|
||
this._vertices[offset + 6] = randomVelocityY;
|
||
this._vertices[offset + 7] = randomVelocityZ;
|
||
}
|
||
switch (this.simulationSpace) {
|
||
case 0:
|
||
offset += 8;
|
||
this._vertices[offset++] = pos.x;
|
||
this._vertices[offset++] = pos.y;
|
||
this._vertices[offset++] = pos.z;
|
||
this._vertices[offset++] = rot.x;
|
||
this._vertices[offset++] = rot.y;
|
||
this._vertices[offset++] = rot.z;
|
||
this._vertices[offset++] = rot.w;
|
||
break;
|
||
case 1:
|
||
break;
|
||
default:
|
||
throw new Error("ShurikenParticleMaterial: SimulationSpace value is invalid.");
|
||
}
|
||
}
|
||
this._firstFreeElement = nextFreeParticle;
|
||
return true;
|
||
}
|
||
addNewParticlesToVertexBuffer() {
|
||
var start;
|
||
var byteStride = this._vertexStride * this._floatCountPerVertex * 4;
|
||
if (this._firstNewElement < this._firstFreeElement) {
|
||
start = this._firstNewElement * byteStride;
|
||
this._vertexBuffer.setData(this._vertices.buffer, start, start, (this._firstFreeElement - this._firstNewElement) * byteStride);
|
||
}
|
||
else {
|
||
start = this._firstNewElement * byteStride;
|
||
this._vertexBuffer.setData(this._vertices.buffer, start, start, (this._bufferMaxParticles - this._firstNewElement) * byteStride);
|
||
if (this._firstFreeElement > 0) {
|
||
this._vertexBuffer.setData(this._vertices.buffer, 0, 0, this._firstFreeElement * byteStride);
|
||
}
|
||
}
|
||
this._firstNewElement = this._firstFreeElement;
|
||
}
|
||
_getType() {
|
||
return ShurikenParticleSystem._type;
|
||
}
|
||
_prepareRender(state) {
|
||
if (this._updateMask != Laya.Stat.loopCount) {
|
||
this._updateMask = Laya.Stat.loopCount;
|
||
this._updateEmission();
|
||
if (this._firstNewElement != this._firstFreeElement)
|
||
this.addNewParticlesToVertexBuffer();
|
||
this._drawCounter++;
|
||
}
|
||
if (this._firstActiveElement != this._firstFreeElement)
|
||
return true;
|
||
else
|
||
return false;
|
||
}
|
||
_render(state) {
|
||
this._bufferState.bind();
|
||
var indexCount;
|
||
var gl = Laya.LayaGL.instance;
|
||
if (this._firstActiveElement < this._firstFreeElement) {
|
||
indexCount = (this._firstFreeElement - this._firstActiveElement) * this._indexStride;
|
||
gl.drawElements(gl.TRIANGLES, indexCount, gl.UNSIGNED_SHORT, 2 * this._firstActiveElement * this._indexStride);
|
||
Laya.Stat.trianglesFaces += indexCount / 3;
|
||
Laya.Stat.renderBatches++;
|
||
}
|
||
else {
|
||
indexCount = (this._bufferMaxParticles - this._firstActiveElement) * this._indexStride;
|
||
gl.drawElements(gl.TRIANGLES, indexCount, gl.UNSIGNED_SHORT, 2 * this._firstActiveElement * this._indexStride);
|
||
Laya.Stat.trianglesFaces += indexCount / 3;
|
||
Laya.Stat.renderBatches++;
|
||
if (this._firstFreeElement > 0) {
|
||
indexCount = this._firstFreeElement * this._indexStride;
|
||
gl.drawElements(gl.TRIANGLES, indexCount, gl.UNSIGNED_SHORT, 0);
|
||
Laya.Stat.trianglesFaces += indexCount / 3;
|
||
Laya.Stat.renderBatches++;
|
||
}
|
||
}
|
||
}
|
||
play() {
|
||
this._burstsIndex = 0;
|
||
this._isEmitting = true;
|
||
this._isPlaying = true;
|
||
this._isPaused = false;
|
||
this._emissionTime = 0;
|
||
this._totalDelayTime = 0;
|
||
if (!this.autoRandomSeed) {
|
||
for (var i = 0, n = this._randomSeeds.length; i < n; i++)
|
||
this._randomSeeds[i] = this.randomSeed[0] + ShurikenParticleSystem._RANDOMOFFSET[i];
|
||
}
|
||
switch (this.startDelayType) {
|
||
case 0:
|
||
this._playStartDelay = this.startDelay;
|
||
break;
|
||
case 1:
|
||
if (this.autoRandomSeed) {
|
||
this._playStartDelay = Laya.MathUtil.lerp(this.startDelayMin, this.startDelayMax, Math.random());
|
||
}
|
||
else {
|
||
this._rand.seed = this._randomSeeds[2];
|
||
this._playStartDelay = Laya.MathUtil.lerp(this.startDelayMin, this.startDelayMax, this._rand.getFloat());
|
||
this._randomSeeds[2] = this._rand.seed;
|
||
}
|
||
break;
|
||
default:
|
||
throw new Error("Utils3D: startDelayType is invalid.");
|
||
}
|
||
this._frameRateTime = this._currentTime + this._playStartDelay;
|
||
this._startUpdateLoopCount = Laya.Stat.loopCount;
|
||
}
|
||
pause() {
|
||
this._isPaused = true;
|
||
}
|
||
simulate(time, restart = true) {
|
||
this._simulateUpdate = true;
|
||
if (restart) {
|
||
this._updateParticlesSimulationRestart(time);
|
||
}
|
||
else {
|
||
this._isPaused = false;
|
||
this._updateParticles(time);
|
||
}
|
||
this.pause();
|
||
}
|
||
stop() {
|
||
this._burstsIndex = 0;
|
||
this._isEmitting = false;
|
||
this._emissionTime = 0;
|
||
}
|
||
cloneTo(destObject) {
|
||
var dest = destObject;
|
||
dest._useCustomBounds = this._useCustomBounds;
|
||
(this._customBounds) && (this._customBounds.cloneTo(dest._customBounds));
|
||
dest.duration = this.duration;
|
||
dest.looping = this.looping;
|
||
dest.prewarm = this.prewarm;
|
||
dest.startDelayType = this.startDelayType;
|
||
dest.startDelay = this.startDelay;
|
||
dest.startDelayMin = this.startDelayMin;
|
||
dest.startDelayMax = this.startDelayMax;
|
||
dest._maxStartLifetime = this._maxStartLifetime;
|
||
dest.startLifetimeType = this.startLifetimeType;
|
||
dest.startLifetimeConstant = this.startLifetimeConstant;
|
||
this.startLifeTimeGradient.cloneTo(dest.startLifeTimeGradient);
|
||
dest.startLifetimeConstantMin = this.startLifetimeConstantMin;
|
||
dest.startLifetimeConstantMax = this.startLifetimeConstantMax;
|
||
this.startLifeTimeGradientMin.cloneTo(dest.startLifeTimeGradientMin);
|
||
this.startLifeTimeGradientMax.cloneTo(dest.startLifeTimeGradientMax);
|
||
dest.startSpeedType = this.startSpeedType;
|
||
dest.startSpeedConstant = this.startSpeedConstant;
|
||
dest.startSpeedConstantMin = this.startSpeedConstantMin;
|
||
dest.startSpeedConstantMax = this.startSpeedConstantMax;
|
||
dest.threeDStartSize = this.threeDStartSize;
|
||
dest.startSizeType = this.startSizeType;
|
||
dest.startSizeConstant = this.startSizeConstant;
|
||
this.startSizeConstantSeparate.cloneTo(dest.startSizeConstantSeparate);
|
||
dest.startSizeConstantMin = this.startSizeConstantMin;
|
||
dest.startSizeConstantMax = this.startSizeConstantMax;
|
||
this.startSizeConstantMinSeparate.cloneTo(dest.startSizeConstantMinSeparate);
|
||
this.startSizeConstantMaxSeparate.cloneTo(dest.startSizeConstantMaxSeparate);
|
||
dest.threeDStartRotation = this.threeDStartRotation;
|
||
dest.startRotationType = this.startRotationType;
|
||
dest.startRotationConstant = this.startRotationConstant;
|
||
this.startRotationConstantSeparate.cloneTo(dest.startRotationConstantSeparate);
|
||
dest.startRotationConstantMin = this.startRotationConstantMin;
|
||
dest.startRotationConstantMax = this.startRotationConstantMax;
|
||
this.startRotationConstantMinSeparate.cloneTo(dest.startRotationConstantMinSeparate);
|
||
this.startRotationConstantMaxSeparate.cloneTo(dest.startRotationConstantMaxSeparate);
|
||
dest.randomizeRotationDirection = this.randomizeRotationDirection;
|
||
dest.startColorType = this.startColorType;
|
||
this.startColorConstant.cloneTo(dest.startColorConstant);
|
||
this.startColorConstantMin.cloneTo(dest.startColorConstantMin);
|
||
this.startColorConstantMax.cloneTo(dest.startColorConstantMax);
|
||
dest.gravityModifier = this.gravityModifier;
|
||
dest.simulationSpace = this.simulationSpace;
|
||
dest.scaleMode = this.scaleMode;
|
||
dest.playOnAwake = this.playOnAwake;
|
||
dest.autoRandomSeed = this.autoRandomSeed;
|
||
dest.randomSeed[0] = this.randomSeed[0];
|
||
dest.maxParticles = this.maxParticles;
|
||
(this._emission) && (dest._emission = this._emission.clone());
|
||
(this.shape) && (dest.shape = this.shape.clone());
|
||
(this.velocityOverLifetime) && (dest.velocityOverLifetime = this.velocityOverLifetime.clone());
|
||
(this.colorOverLifetime) && (dest.colorOverLifetime = this.colorOverLifetime.clone());
|
||
(this.sizeOverLifetime) && (dest.sizeOverLifetime = this.sizeOverLifetime.clone());
|
||
(this.rotationOverLifetime) && (dest.rotationOverLifetime = this.rotationOverLifetime.clone());
|
||
(this.textureSheetAnimation) && (dest.textureSheetAnimation = this.textureSheetAnimation.clone());
|
||
dest.isPerformanceMode = this.isPerformanceMode;
|
||
dest._isEmitting = this._isEmitting;
|
||
dest._isPlaying = this._isPlaying;
|
||
dest._isPaused = this._isPaused;
|
||
dest._playStartDelay = this._playStartDelay;
|
||
dest._frameRateTime = this._frameRateTime;
|
||
dest._emissionTime = this._emissionTime;
|
||
dest._totalDelayTime = this._totalDelayTime;
|
||
dest._burstsIndex = this._burstsIndex;
|
||
}
|
||
clone() {
|
||
var dest = new ShurikenParticleSystem(null);
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
}
|
||
ShurikenParticleSystem._RANDOMOFFSET = new Uint32Array([0x23571a3e, 0xc34f56fe, 0x13371337, 0x12460f3b, 0x6aed452e, 0xdec4aea1, 0x96aa4de3, 0x8d2c8431, 0xf3857f6f, 0xe0fbd834, 0x13740583, 0x591bc05c, 0x40eb95e4, 0xbc524e5f, 0xaf502044, 0xa614b381, 0x1034e524, 0xfc524e5f]);
|
||
ShurikenParticleSystem.halfKSqrtOf2 = 1.42 * 0.5;
|
||
ShurikenParticleSystem.g = 9.8;
|
||
ShurikenParticleSystem._maxElapsedTime = 1.0 / 3.0;
|
||
ShurikenParticleSystem._tempVector30 = new Vector3();
|
||
ShurikenParticleSystem._tempVector31 = new Vector3();
|
||
ShurikenParticleSystem._tempVector32 = new Vector3();
|
||
ShurikenParticleSystem._tempVector33 = new Vector3();
|
||
ShurikenParticleSystem._tempVector34 = new Vector3();
|
||
ShurikenParticleSystem._tempVector35 = new Vector3();
|
||
ShurikenParticleSystem._tempVector36 = new Vector3();
|
||
ShurikenParticleSystem._tempVector37 = new Vector3();
|
||
ShurikenParticleSystem._tempPosition = new Vector3();
|
||
ShurikenParticleSystem._tempDirection = new Vector3();
|
||
ShurikenParticleSystem._type = GeometryElement._typeCounter++;
|
||
|
||
class ShuriKenParticle3D extends RenderableSprite3D {
|
||
constructor() {
|
||
super(null);
|
||
this._render = new ShurikenParticleRenderer(this);
|
||
this._particleSystem = new ShurikenParticleSystem(this);
|
||
var elements = this._render._renderElements;
|
||
var element = elements[0] = new RenderElement();
|
||
element.setTransform(this._transform);
|
||
element.render = this._render;
|
||
element.setGeometry(this._particleSystem);
|
||
element.material = ShurikenParticleMaterial.defaultMaterial;
|
||
}
|
||
static __init__() {
|
||
ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_BILLBOARD = Shader3D.getDefineByName("SPHERHBILLBOARD");
|
||
ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_STRETCHEDBILLBOARD = Shader3D.getDefineByName("STRETCHEDBILLBOARD");
|
||
ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_HORIZONTALBILLBOARD = Shader3D.getDefineByName("HORIZONTALBILLBOARD");
|
||
ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_VERTICALBILLBOARD = Shader3D.getDefineByName("VERTICALBILLBOARD");
|
||
ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_COLOROVERLIFETIME = Shader3D.getDefineByName("COLOROVERLIFETIME");
|
||
ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RANDOMCOLOROVERLIFETIME = Shader3D.getDefineByName("RANDOMCOLOROVERLIFETIME");
|
||
ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMECONSTANT = Shader3D.getDefineByName("VELOCITYOVERLIFETIMECONSTANT");
|
||
ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMECURVE = Shader3D.getDefineByName("VELOCITYOVERLIFETIMECURVE");
|
||
ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMERANDOMCONSTANT = Shader3D.getDefineByName("VELOCITYOVERLIFETIMERANDOMCONSTANT");
|
||
ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_VELOCITYOVERLIFETIMERANDOMCURVE = Shader3D.getDefineByName("VELOCITYOVERLIFETIMERANDOMCURVE");
|
||
ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_TEXTURESHEETANIMATIONCURVE = Shader3D.getDefineByName("TEXTURESHEETANIMATIONCURVE");
|
||
ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_TEXTURESHEETANIMATIONRANDOMCURVE = Shader3D.getDefineByName("TEXTURESHEETANIMATIONRANDOMCURVE");
|
||
ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIME = Shader3D.getDefineByName("ROTATIONOVERLIFETIME");
|
||
ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMESEPERATE = Shader3D.getDefineByName("ROTATIONOVERLIFETIMESEPERATE");
|
||
ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMECONSTANT = Shader3D.getDefineByName("ROTATIONOVERLIFETIMECONSTANT");
|
||
ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMECURVE = Shader3D.getDefineByName("ROTATIONOVERLIFETIMECURVE");
|
||
ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMERANDOMCONSTANTS = Shader3D.getDefineByName("ROTATIONOVERLIFETIMERANDOMCONSTANTS");
|
||
ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_ROTATIONOVERLIFETIMERANDOMCURVES = Shader3D.getDefineByName("ROTATIONOVERLIFETIMERANDOMCURVES");
|
||
ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMECURVE = Shader3D.getDefineByName("SIZEOVERLIFETIMECURVE");
|
||
ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMECURVESEPERATE = Shader3D.getDefineByName("SIZEOVERLIFETIMECURVESEPERATE");
|
||
ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMERANDOMCURVES = Shader3D.getDefineByName("SIZEOVERLIFETIMERANDOMCURVES");
|
||
ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SIZEOVERLIFETIMERANDOMCURVESSEPERATE = Shader3D.getDefineByName("SIZEOVERLIFETIMERANDOMCURVESSEPERATE");
|
||
ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_RENDERMODE_MESH = Shader3D.getDefineByName("RENDERMODE_MESH");
|
||
ShuriKenParticle3DShaderDeclaration.SHADERDEFINE_SHAPE = Shader3D.getDefineByName("SHAPE");
|
||
}
|
||
get particleSystem() {
|
||
return this._particleSystem;
|
||
}
|
||
get particleRenderer() {
|
||
return this._render;
|
||
}
|
||
_parseModule(module, moduleData) {
|
||
for (var t in moduleData) {
|
||
switch (t) {
|
||
case "bases":
|
||
var bases = moduleData.bases;
|
||
for (var k in bases)
|
||
module[k] = bases[k];
|
||
break;
|
||
case "vector2s":
|
||
var vector2s = moduleData.vector2s;
|
||
for (var k in vector2s) {
|
||
var vec2 = module[k];
|
||
var vec2Data = vector2s[k];
|
||
vec2.setValue(vec2Data[0], vec2Data[1]);
|
||
module[k] = vec2;
|
||
}
|
||
break;
|
||
case "vector3s":
|
||
var vector3s = moduleData.vector3s;
|
||
for (var k in vector3s) {
|
||
var vec3 = module[k];
|
||
var vec3Data = vector3s[k];
|
||
vec3.setValue(vec3Data[0], vec3Data[1], vec3Data[2]);
|
||
module[k] = vec3;
|
||
}
|
||
break;
|
||
case "vector4s":
|
||
var vector4s = moduleData.vector4s;
|
||
for (var k in vector4s) {
|
||
var vec4 = module[k];
|
||
var vec4Data = vector4s[k];
|
||
vec4.setValue(vec4Data[0], vec4Data[1], vec4Data[2], vec4Data[3]);
|
||
module[k] = vec4;
|
||
}
|
||
break;
|
||
case "gradientDataNumbers":
|
||
var gradientDataNumbers = moduleData.gradientDataNumbers;
|
||
for (var k in gradientDataNumbers) {
|
||
var gradientNumber = module[k];
|
||
var gradientNumberData = moduleData[k];
|
||
for (var i = 0, n = gradientNumberData.length; i < n; i++) {
|
||
var valueData = gradientNumberData[i];
|
||
gradientNumber.add(valueData.key, valueData.value);
|
||
}
|
||
module[k] = gradientNumber;
|
||
}
|
||
break;
|
||
case "resources":
|
||
var resources = moduleData.resources;
|
||
for (var k in resources)
|
||
module[k] = Laya.Loader.getRes(resources[k]);
|
||
break;
|
||
case "bursts":
|
||
var burstsData = moduleData.bursts;
|
||
for (var i = 0, n = burstsData.length; i < n; i++) {
|
||
var brust = burstsData[i];
|
||
module.addBurst(new Burst(brust.time, brust.min, brust.max));
|
||
}
|
||
break;
|
||
case "randomSeed":
|
||
module.randomSeed[0] = moduleData.randomSeed;
|
||
break;
|
||
case "shapeType":
|
||
case "type":
|
||
case "color":
|
||
case "size":
|
||
case "frame":
|
||
case "startFrame":
|
||
case "angularVelocity":
|
||
case "velocity":
|
||
break;
|
||
default:
|
||
throw "ShurikenParticle3D:unknown type.";
|
||
}
|
||
}
|
||
}
|
||
_parse(data, spriteMap) {
|
||
super._parse(data, spriteMap);
|
||
if (data.main) {
|
||
var particleSystem = this.particleSystem;
|
||
var particleRender = this.particleRenderer;
|
||
this._parseModule(particleRender, data.renderer);
|
||
this._parseModule(particleSystem, data.main);
|
||
this._parseModule(particleSystem.emission, data.emission);
|
||
var shapeData = data.shape;
|
||
if (shapeData) {
|
||
var shape;
|
||
switch (shapeData.shapeType) {
|
||
case 0:
|
||
shape = new SphereShape();
|
||
break;
|
||
case 1:
|
||
shape = new HemisphereShape();
|
||
break;
|
||
case 2:
|
||
shape = new ConeShape();
|
||
break;
|
||
case 3:
|
||
shape = new BoxShape();
|
||
break;
|
||
case 7:
|
||
shape = new CircleShape();
|
||
break;
|
||
default:
|
||
throw "ShuriKenParticle3D:unknown shape type.";
|
||
}
|
||
this._parseModule(shape, shapeData);
|
||
particleSystem.shape = shape;
|
||
}
|
||
var velocityOverLifetimeData = data.velocityOverLifetime;
|
||
if (velocityOverLifetimeData) {
|
||
var velocityData = velocityOverLifetimeData.velocity;
|
||
var velocity;
|
||
switch (velocityData.type) {
|
||
case 0:
|
||
var constantData = velocityData.constant;
|
||
velocity = GradientVelocity.createByConstant(constantData ? new Vector3(constantData[0], constantData[1], constantData[2]) : new Vector3(0, 0, 0));
|
||
break;
|
||
case 1:
|
||
velocity = GradientVelocity.createByGradient(this._initParticleVelocity(velocityData.gradientX), this._initParticleVelocity(velocityData.gradientY), this._initParticleVelocity(velocityData.gradientZ));
|
||
break;
|
||
case 2:
|
||
var constantMinData = velocityData.constantMin;
|
||
var constantMaxData = velocityData.constantMax;
|
||
velocity = GradientVelocity.createByRandomTwoConstant(constantMinData ? new Vector3(constantMinData[0], constantMinData[1], constantMinData[2]) : new Vector3(0, 0, 0), constantMaxData ? new Vector3(constantMaxData[0], constantMaxData[1], constantMaxData[2]) : new Vector3(0, 0, 0));
|
||
break;
|
||
case 3:
|
||
velocity = GradientVelocity.createByRandomTwoGradient(this._initParticleVelocity(velocityData.gradientXMin), this._initParticleVelocity(velocityData.gradientXMax), this._initParticleVelocity(velocityData.gradientYMin), this._initParticleVelocity(velocityData.gradientYMax), this._initParticleVelocity(velocityData.gradientZMin), this._initParticleVelocity(velocityData.gradientZMax));
|
||
break;
|
||
}
|
||
var velocityOverLifetime = new VelocityOverLifetime(velocity);
|
||
this._parseModule(velocityOverLifetime, velocityOverLifetimeData);
|
||
particleSystem.velocityOverLifetime = velocityOverLifetime;
|
||
}
|
||
var colorOverLifetimeData = data.colorOverLifetime;
|
||
if (colorOverLifetimeData) {
|
||
var colorData = colorOverLifetimeData.color;
|
||
var color;
|
||
switch (colorData.type) {
|
||
case 0:
|
||
var constColorData = colorData.constant;
|
||
color = GradientColor.createByConstant(constColorData ? new Vector4(constColorData[0], constColorData[1], constColorData[2], constColorData[3]) : new Vector4(0, 0, 0, 0));
|
||
break;
|
||
case 1:
|
||
color = GradientColor.createByGradient(this._initParticleColor(colorData.gradient));
|
||
break;
|
||
case 2:
|
||
var minConstColorData = colorData.constantMin;
|
||
var maxConstColorData = colorData.constantMax;
|
||
color = GradientColor.createByRandomTwoConstant(minConstColorData ? new Vector4(minConstColorData[0], minConstColorData[1], minConstColorData[2], minConstColorData[3]) : new Vector4(0, 0, 0, 0), minConstColorData ? new Vector4(maxConstColorData[0], maxConstColorData[1], maxConstColorData[2], maxConstColorData[3]) : new Vector4(0, 0, 0, 0));
|
||
break;
|
||
case 3:
|
||
color = GradientColor.createByRandomTwoGradient(this._initParticleColor(colorData.gradientMin), this._initParticleColor(colorData.gradientMax));
|
||
break;
|
||
}
|
||
var colorOverLifetime = new ColorOverLifetime(color);
|
||
this._parseModule(colorOverLifetime, colorOverLifetimeData);
|
||
particleSystem.colorOverLifetime = colorOverLifetime;
|
||
}
|
||
var sizeOverLifetimeData = data.sizeOverLifetime;
|
||
if (sizeOverLifetimeData) {
|
||
var sizeData = sizeOverLifetimeData.size;
|
||
var size;
|
||
switch (sizeData.type) {
|
||
case 0:
|
||
if (sizeData.separateAxes) {
|
||
size = GradientSize.createByGradientSeparate(this._initParticleSize(sizeData.gradientX), this._initParticleSize(sizeData.gradientY), this._initParticleSize(sizeData.gradientZ));
|
||
}
|
||
else {
|
||
size = GradientSize.createByGradient(this._initParticleSize(sizeData.gradient));
|
||
}
|
||
break;
|
||
case 1:
|
||
if (sizeData.separateAxes) {
|
||
var constantMinSeparateData = sizeData.constantMinSeparate;
|
||
var constantMaxSeparateData = sizeData.constantMaxSeparate;
|
||
size = GradientSize.createByRandomTwoConstantSeparate(constantMinSeparateData ? new Vector3(constantMinSeparateData[0], constantMinSeparateData[1], constantMinSeparateData[2]) : new Vector3(0, 0, 0), constantMaxSeparateData ? new Vector3(constantMaxSeparateData[0], constantMaxSeparateData[1], constantMaxSeparateData[2]) : new Vector3(0, 0, 0));
|
||
}
|
||
else {
|
||
size = GradientSize.createByRandomTwoConstant(sizeData.constantMin || 0, sizeData.constantMax || 0);
|
||
}
|
||
break;
|
||
case 2:
|
||
if (sizeData.separateAxes) {
|
||
size = GradientSize.createByRandomTwoGradientSeparate(this._initParticleSize(sizeData.gradientXMin), this._initParticleSize(sizeData.gradientYMin), this._initParticleSize(sizeData.gradientZMin), this._initParticleSize(sizeData.gradientXMax), this._initParticleSize(sizeData.gradientYMax), this._initParticleSize(sizeData.gradientZMax));
|
||
}
|
||
else {
|
||
size = GradientSize.createByRandomTwoGradient(this._initParticleSize(sizeData.gradientMin), this._initParticleSize(sizeData.gradientMax));
|
||
}
|
||
break;
|
||
}
|
||
var sizeOverLifetime = new SizeOverLifetime(size);
|
||
this._parseModule(sizeOverLifetime, sizeOverLifetimeData);
|
||
particleSystem.sizeOverLifetime = sizeOverLifetime;
|
||
}
|
||
var rotationOverLifetimeData = data.rotationOverLifetime;
|
||
if (rotationOverLifetimeData) {
|
||
var angularVelocityData = rotationOverLifetimeData.angularVelocity;
|
||
var angularVelocity;
|
||
switch (angularVelocityData.type) {
|
||
case 0:
|
||
if (angularVelocityData.separateAxes) {
|
||
var conSep = angularVelocityData.constantSeparate;
|
||
angularVelocity = GradientAngularVelocity.createByConstantSeparate(conSep ? new Vector3(conSep[0], conSep[1], conSep[2]) : new Vector3(0, 0, Math.PI / 4));
|
||
}
|
||
else {
|
||
angularVelocity = GradientAngularVelocity.createByConstant(angularVelocityData.constant || Math.PI / 4);
|
||
}
|
||
break;
|
||
case 1:
|
||
if (angularVelocityData.separateAxes) {
|
||
angularVelocity = GradientAngularVelocity.createByGradientSeparate(this._initParticleRotation(angularVelocityData.gradientX), this._initParticleRotation(angularVelocityData.gradientY), this._initParticleRotation(angularVelocityData.gradientZ));
|
||
}
|
||
else {
|
||
angularVelocity = GradientAngularVelocity.createByGradient(this._initParticleRotation(angularVelocityData.gradient));
|
||
}
|
||
break;
|
||
case 2:
|
||
if (angularVelocityData.separateAxes) {
|
||
var minSep = angularVelocityData.constantMinSeparate;
|
||
var maxSep = angularVelocityData.constantMaxSeparate;
|
||
angularVelocity = GradientAngularVelocity.createByRandomTwoConstantSeparate(minSep ? new Vector3(minSep[0], minSep[1], minSep[2]) : new Vector3(0, 0, 0), maxSep ? new Vector3(maxSep[0], maxSep[1], maxSep[2]) : new Vector3(0, 0, Math.PI / 4));
|
||
}
|
||
else {
|
||
angularVelocity = GradientAngularVelocity.createByRandomTwoConstant(angularVelocityData.constantMin || 0, angularVelocityData.constantMax || Math.PI / 4);
|
||
}
|
||
break;
|
||
case 3:
|
||
if (angularVelocityData.separateAxes) ;
|
||
else {
|
||
angularVelocity = GradientAngularVelocity.createByRandomTwoGradient(this._initParticleRotation(angularVelocityData.gradientMin), this._initParticleRotation(angularVelocityData.gradientMax));
|
||
}
|
||
break;
|
||
}
|
||
var rotationOverLifetime = new RotationOverLifetime(angularVelocity);
|
||
this._parseModule(rotationOverLifetime, rotationOverLifetimeData);
|
||
particleSystem.rotationOverLifetime = rotationOverLifetime;
|
||
}
|
||
var textureSheetAnimationData = data.textureSheetAnimation;
|
||
if (textureSheetAnimationData) {
|
||
var frameData = textureSheetAnimationData.frame;
|
||
var frameOverTime;
|
||
switch (frameData.type) {
|
||
case 0:
|
||
frameOverTime = FrameOverTime.createByConstant(frameData.constant);
|
||
break;
|
||
case 1:
|
||
frameOverTime = FrameOverTime.createByOverTime(this._initParticleFrame(frameData.overTime));
|
||
break;
|
||
case 2:
|
||
frameOverTime = FrameOverTime.createByRandomTwoConstant(frameData.constantMin, frameData.constantMax);
|
||
break;
|
||
case 3:
|
||
frameOverTime = FrameOverTime.createByRandomTwoOverTime(this._initParticleFrame(frameData.overTimeMin), this._initParticleFrame(frameData.overTimeMax));
|
||
break;
|
||
}
|
||
var startFrameData = textureSheetAnimationData.startFrame;
|
||
var startFrame;
|
||
switch (startFrameData.type) {
|
||
case 0:
|
||
startFrame = StartFrame.createByConstant(startFrameData.constant);
|
||
break;
|
||
case 1:
|
||
startFrame = StartFrame.createByRandomTwoConstant(startFrameData.constantMin, startFrameData.constantMax);
|
||
break;
|
||
}
|
||
var textureSheetAnimation = new TextureSheetAnimation(frameOverTime, startFrame);
|
||
this._parseModule(textureSheetAnimation, textureSheetAnimationData);
|
||
particleSystem.textureSheetAnimation = textureSheetAnimation;
|
||
}
|
||
}
|
||
else {
|
||
this._parseOld(data);
|
||
}
|
||
}
|
||
_activeHierarchy(activeChangeComponents) {
|
||
super._activeHierarchy(activeChangeComponents);
|
||
(this.particleSystem.playOnAwake) && (this.particleSystem.play());
|
||
}
|
||
_inActiveHierarchy(activeChangeComponents) {
|
||
super._inActiveHierarchy(activeChangeComponents);
|
||
(this.particleSystem.isAlive) && (this.particleSystem.simulate(0, true));
|
||
}
|
||
_cloneTo(destObject, srcSprite, dstSprite) {
|
||
var destShuriKenParticle3D = destObject;
|
||
var destParticleSystem = destShuriKenParticle3D._particleSystem;
|
||
this._particleSystem.cloneTo(destParticleSystem);
|
||
var destParticleRender = destShuriKenParticle3D._render;
|
||
var particleRender = this._render;
|
||
destParticleRender.sharedMaterials = particleRender.sharedMaterials;
|
||
destParticleRender.enable = particleRender.enable;
|
||
destParticleRender.renderMode = particleRender.renderMode;
|
||
destParticleRender.mesh = particleRender.mesh;
|
||
destParticleRender.stretchedBillboardCameraSpeedScale = particleRender.stretchedBillboardCameraSpeedScale;
|
||
destParticleRender.stretchedBillboardSpeedScale = particleRender.stretchedBillboardSpeedScale;
|
||
destParticleRender.stretchedBillboardLengthScale = particleRender.stretchedBillboardLengthScale;
|
||
destParticleRender.sortingFudge = particleRender.sortingFudge;
|
||
super._cloneTo(destObject, srcSprite, dstSprite);
|
||
}
|
||
destroy(destroyChild = true) {
|
||
if (this.destroyed)
|
||
return;
|
||
super.destroy(destroyChild);
|
||
this._particleSystem.destroy();
|
||
this._particleSystem = null;
|
||
}
|
||
_create() {
|
||
return new ShuriKenParticle3D();
|
||
}
|
||
_parseOld(data) {
|
||
const anglelToRad = Math.PI / 180.0;
|
||
var i, n;
|
||
var particleRender = this.particleRenderer;
|
||
var material;
|
||
var materialData = data.material;
|
||
(materialData) && (material = Laya.Loader.getRes(materialData.path));
|
||
particleRender.sharedMaterial = material;
|
||
var meshPath = data.meshPath;
|
||
(meshPath) && (particleRender.mesh = Laya.Loader.getRes(meshPath));
|
||
particleRender.renderMode = data.renderMode;
|
||
particleRender.stretchedBillboardCameraSpeedScale = data.stretchedBillboardCameraSpeedScale;
|
||
particleRender.stretchedBillboardSpeedScale = data.stretchedBillboardSpeedScale;
|
||
particleRender.stretchedBillboardLengthScale = data.stretchedBillboardLengthScale;
|
||
particleRender.sortingFudge = data.sortingFudge ? data.sortingFudge : 0.0;
|
||
var particleSystem = this.particleSystem;
|
||
particleSystem.isPerformanceMode = data.isPerformanceMode;
|
||
particleSystem.duration = data.duration;
|
||
particleSystem.looping = data.looping;
|
||
particleSystem.prewarm = data.prewarm;
|
||
particleSystem.startDelayType = data.startDelayType;
|
||
particleSystem.startDelay = data.startDelay;
|
||
particleSystem.startDelayMin = data.startDelayMin;
|
||
particleSystem.startDelayMax = data.startDelayMax;
|
||
particleSystem.startLifetimeType = data.startLifetimeType;
|
||
particleSystem.startLifetimeConstant = data.startLifetimeConstant;
|
||
particleSystem.startLifeTimeGradient = ShuriKenParticle3D._initStartLife(data.startLifetimeGradient);
|
||
particleSystem.startLifetimeConstantMin = data.startLifetimeConstantMin;
|
||
particleSystem.startLifetimeConstantMax = data.startLifetimeConstantMax;
|
||
particleSystem.startLifeTimeGradientMin = ShuriKenParticle3D._initStartLife(data.startLifetimeGradientMin);
|
||
particleSystem.startLifeTimeGradientMax = ShuriKenParticle3D._initStartLife(data.startLifetimeGradientMax);
|
||
particleSystem.startSpeedType = data.startSpeedType;
|
||
particleSystem.startSpeedConstant = data.startSpeedConstant;
|
||
particleSystem.startSpeedConstantMin = data.startSpeedConstantMin;
|
||
particleSystem.startSpeedConstantMax = data.startSpeedConstantMax;
|
||
particleSystem.threeDStartSize = data.threeDStartSize;
|
||
particleSystem.startSizeType = data.startSizeType;
|
||
particleSystem.startSizeConstant = data.startSizeConstant;
|
||
var startSizeConstantSeparateArray = data.startSizeConstantSeparate;
|
||
var startSizeConstantSeparateElement = particleSystem.startSizeConstantSeparate;
|
||
startSizeConstantSeparateElement.x = startSizeConstantSeparateArray[0];
|
||
startSizeConstantSeparateElement.y = startSizeConstantSeparateArray[1];
|
||
startSizeConstantSeparateElement.z = startSizeConstantSeparateArray[2];
|
||
particleSystem.startSizeConstantMin = data.startSizeConstantMin;
|
||
particleSystem.startSizeConstantMax = data.startSizeConstantMax;
|
||
var startSizeConstantMinSeparateArray = data.startSizeConstantMinSeparate;
|
||
var startSizeConstantMinSeparateElement = particleSystem.startSizeConstantMinSeparate;
|
||
startSizeConstantMinSeparateElement.x = startSizeConstantMinSeparateArray[0];
|
||
startSizeConstantMinSeparateElement.y = startSizeConstantMinSeparateArray[1];
|
||
startSizeConstantMinSeparateElement.z = startSizeConstantMinSeparateArray[2];
|
||
var startSizeConstantMaxSeparateArray = data.startSizeConstantMaxSeparate;
|
||
var startSizeConstantMaxSeparateElement = particleSystem.startSizeConstantMaxSeparate;
|
||
startSizeConstantMaxSeparateElement.x = startSizeConstantMaxSeparateArray[0];
|
||
startSizeConstantMaxSeparateElement.y = startSizeConstantMaxSeparateArray[1];
|
||
startSizeConstantMaxSeparateElement.z = startSizeConstantMaxSeparateArray[2];
|
||
particleSystem.threeDStartRotation = data.threeDStartRotation;
|
||
particleSystem.startRotationType = data.startRotationType;
|
||
particleSystem.startRotationConstant = data.startRotationConstant * anglelToRad;
|
||
var startRotationConstantSeparateArray = data.startRotationConstantSeparate;
|
||
var startRotationConstantSeparateElement = particleSystem.startRotationConstantSeparate;
|
||
startRotationConstantSeparateElement.x = startRotationConstantSeparateArray[0] * anglelToRad;
|
||
startRotationConstantSeparateElement.y = startRotationConstantSeparateArray[1] * anglelToRad;
|
||
startRotationConstantSeparateElement.z = startRotationConstantSeparateArray[2] * anglelToRad;
|
||
particleSystem.startRotationConstantMin = data.startRotationConstantMin * anglelToRad;
|
||
particleSystem.startRotationConstantMax = data.startRotationConstantMax * anglelToRad;
|
||
var startRotationConstantMinSeparateArray = data.startRotationConstantMinSeparate;
|
||
var startRotationConstantMinSeparateElement = particleSystem.startRotationConstantMinSeparate;
|
||
startRotationConstantMinSeparateElement.x = startRotationConstantMinSeparateArray[0] * anglelToRad;
|
||
startRotationConstantMinSeparateElement.y = startRotationConstantMinSeparateArray[1] * anglelToRad;
|
||
startRotationConstantMinSeparateElement.z = startRotationConstantMinSeparateArray[2] * anglelToRad;
|
||
var startRotationConstantMaxSeparateArray = data.startRotationConstantMaxSeparate;
|
||
var startRotationConstantMaxSeparateElement = particleSystem.startRotationConstantMaxSeparate;
|
||
startRotationConstantMaxSeparateElement.x = startRotationConstantMaxSeparateArray[0] * anglelToRad;
|
||
startRotationConstantMaxSeparateElement.y = startRotationConstantMaxSeparateArray[1] * anglelToRad;
|
||
startRotationConstantMaxSeparateElement.z = startRotationConstantMaxSeparateArray[2] * anglelToRad;
|
||
particleSystem.randomizeRotationDirection = data.randomizeRotationDirection;
|
||
particleSystem.startColorType = data.startColorType;
|
||
var startColorConstantArray = data.startColorConstant;
|
||
var startColorConstantElement = particleSystem.startColorConstant;
|
||
startColorConstantElement.x = startColorConstantArray[0];
|
||
startColorConstantElement.y = startColorConstantArray[1];
|
||
startColorConstantElement.z = startColorConstantArray[2];
|
||
startColorConstantElement.w = startColorConstantArray[3];
|
||
var startColorConstantMinArray = data.startColorConstantMin;
|
||
var startColorConstantMinElement = particleSystem.startColorConstantMin;
|
||
startColorConstantMinElement.x = startColorConstantMinArray[0];
|
||
startColorConstantMinElement.y = startColorConstantMinArray[1];
|
||
startColorConstantMinElement.z = startColorConstantMinArray[2];
|
||
startColorConstantMinElement.w = startColorConstantMinArray[3];
|
||
var startColorConstantMaxArray = data.startColorConstantMax;
|
||
var startColorConstantMaxElement = particleSystem.startColorConstantMax;
|
||
startColorConstantMaxElement.x = startColorConstantMaxArray[0];
|
||
startColorConstantMaxElement.y = startColorConstantMaxArray[1];
|
||
startColorConstantMaxElement.z = startColorConstantMaxArray[2];
|
||
startColorConstantMaxElement.w = startColorConstantMaxArray[3];
|
||
particleSystem.gravityModifier = data.gravityModifier;
|
||
particleSystem.simulationSpace = data.simulationSpace;
|
||
(data.simulationSpeed !== undefined) && (particleSystem.simulationSpeed = data.simulationSpeed);
|
||
particleSystem.scaleMode = data.scaleMode;
|
||
particleSystem.playOnAwake = data.playOnAwake;
|
||
particleSystem.maxParticles = data.maxParticles;
|
||
var autoRandomSeed = data.autoRandomSeed;
|
||
(autoRandomSeed != null) && (particleSystem.autoRandomSeed = autoRandomSeed);
|
||
var randomSeed = data.randomSeed;
|
||
(randomSeed != null) && (particleSystem.randomSeed[0] = randomSeed);
|
||
var emissionData = data.emission;
|
||
var emission = particleSystem.emission;
|
||
if (emissionData) {
|
||
emission.emissionRate = emissionData.emissionRate;
|
||
var burstsData = emissionData.bursts;
|
||
if (burstsData)
|
||
for (i = 0, n = burstsData.length; i < n; i++) {
|
||
var brust = burstsData[i];
|
||
emission.addBurst(new Burst(brust.time, brust.min, brust.max));
|
||
}
|
||
emission.enable = emissionData.enable;
|
||
}
|
||
else {
|
||
emission.enable = false;
|
||
}
|
||
var shapeData = data.shape;
|
||
if (shapeData) {
|
||
var shape;
|
||
switch (shapeData.shapeType) {
|
||
case 0:
|
||
var sphereShape;
|
||
shape = sphereShape = new SphereShape();
|
||
sphereShape.radius = shapeData.sphereRadius;
|
||
sphereShape.emitFromShell = shapeData.sphereEmitFromShell;
|
||
sphereShape.randomDirection = shapeData.sphereRandomDirection;
|
||
break;
|
||
case 1:
|
||
var hemiSphereShape;
|
||
shape = hemiSphereShape = new HemisphereShape();
|
||
hemiSphereShape.radius = shapeData.hemiSphereRadius;
|
||
hemiSphereShape.emitFromShell = shapeData.hemiSphereEmitFromShell;
|
||
hemiSphereShape.randomDirection = shapeData.hemiSphereRandomDirection;
|
||
break;
|
||
case 2:
|
||
var coneShape;
|
||
shape = coneShape = new ConeShape();
|
||
coneShape.angle = shapeData.coneAngle * anglelToRad;
|
||
coneShape.radius = shapeData.coneRadius;
|
||
coneShape.length = shapeData.coneLength;
|
||
coneShape.emitType = shapeData.coneEmitType;
|
||
coneShape.randomDirection = shapeData.coneRandomDirection;
|
||
break;
|
||
case 3:
|
||
var boxShape;
|
||
shape = boxShape = new BoxShape();
|
||
boxShape.x = shapeData.boxX;
|
||
boxShape.y = shapeData.boxY;
|
||
boxShape.z = shapeData.boxZ;
|
||
boxShape.randomDirection = shapeData.boxRandomDirection;
|
||
break;
|
||
case 7:
|
||
var circleShape;
|
||
shape = circleShape = new CircleShape();
|
||
circleShape.radius = shapeData.circleRadius;
|
||
circleShape.arc = shapeData.circleArc * anglelToRad;
|
||
circleShape.emitFromEdge = shapeData.circleEmitFromEdge;
|
||
circleShape.randomDirection = shapeData.circleRandomDirection;
|
||
break;
|
||
default:
|
||
var tempShape;
|
||
shape = tempShape = new CircleShape();
|
||
tempShape.radius = shapeData.circleRadius;
|
||
tempShape.arc = shapeData.circleArc * anglelToRad;
|
||
tempShape.emitFromEdge = shapeData.circleEmitFromEdge;
|
||
tempShape.randomDirection = shapeData.circleRandomDirection;
|
||
break;
|
||
}
|
||
shape.enable = shapeData.enable;
|
||
particleSystem.shape = shape;
|
||
}
|
||
var velocityOverLifetimeData = data.velocityOverLifetime;
|
||
if (velocityOverLifetimeData) {
|
||
var velocityData = velocityOverLifetimeData.velocity;
|
||
var velocity;
|
||
switch (velocityData.type) {
|
||
case 0:
|
||
var constantData = velocityData.constant;
|
||
velocity = GradientVelocity.createByConstant(new Vector3(constantData[0], constantData[1], constantData[2]));
|
||
break;
|
||
case 1:
|
||
velocity = GradientVelocity.createByGradient(this._initParticleVelocity(velocityData.gradientX), this._initParticleVelocity(velocityData.gradientY), this._initParticleVelocity(velocityData.gradientZ));
|
||
break;
|
||
case 2:
|
||
var constantMinData = velocityData.constantMin;
|
||
var constantMaxData = velocityData.constantMax;
|
||
velocity = GradientVelocity.createByRandomTwoConstant(new Vector3(constantMinData[0], constantMinData[1], constantMinData[2]), new Vector3(constantMaxData[0], constantMaxData[1], constantMaxData[2]));
|
||
break;
|
||
case 3:
|
||
velocity = GradientVelocity.createByRandomTwoGradient(this._initParticleVelocity(velocityData.gradientXMin), this._initParticleVelocity(velocityData.gradientXMax), this._initParticleVelocity(velocityData.gradientYMin), this._initParticleVelocity(velocityData.gradientYMax), this._initParticleVelocity(velocityData.gradientZMin), this._initParticleVelocity(velocityData.gradientZMax));
|
||
break;
|
||
}
|
||
var velocityOverLifetime = new VelocityOverLifetime(velocity);
|
||
velocityOverLifetime.space = velocityOverLifetimeData.space;
|
||
velocityOverLifetime.enable = velocityOverLifetimeData.enable;
|
||
particleSystem.velocityOverLifetime = velocityOverLifetime;
|
||
}
|
||
var colorOverLifetimeData = data.colorOverLifetime;
|
||
if (colorOverLifetimeData) {
|
||
var colorData = colorOverLifetimeData.color;
|
||
var color;
|
||
switch (colorData.type) {
|
||
case 0:
|
||
var constColorData = colorData.constant;
|
||
color = GradientColor.createByConstant(new Vector4(constColorData[0], constColorData[1], constColorData[2], constColorData[3]));
|
||
break;
|
||
case 1:
|
||
color = GradientColor.createByGradient(this._initParticleColor(colorData.gradient));
|
||
break;
|
||
case 2:
|
||
var minConstColorData = colorData.constantMin;
|
||
var maxConstColorData = colorData.constantMax;
|
||
color = GradientColor.createByRandomTwoConstant(new Vector4(minConstColorData[0], minConstColorData[1], minConstColorData[2], minConstColorData[3]), new Vector4(maxConstColorData[0], maxConstColorData[1], maxConstColorData[2], maxConstColorData[3]));
|
||
break;
|
||
case 3:
|
||
color = GradientColor.createByRandomTwoGradient(this._initParticleColor(colorData.gradientMin), this._initParticleColor(colorData.gradientMax));
|
||
break;
|
||
}
|
||
var colorOverLifetime = new ColorOverLifetime(color);
|
||
colorOverLifetime.enable = colorOverLifetimeData.enable;
|
||
particleSystem.colorOverLifetime = colorOverLifetime;
|
||
}
|
||
var sizeOverLifetimeData = data.sizeOverLifetime;
|
||
if (sizeOverLifetimeData) {
|
||
var sizeData = sizeOverLifetimeData.size;
|
||
var size;
|
||
switch (sizeData.type) {
|
||
case 0:
|
||
if (sizeData.separateAxes) {
|
||
size = GradientSize.createByGradientSeparate(this._initParticleSize(sizeData.gradientX), this._initParticleSize(sizeData.gradientY), this._initParticleSize(sizeData.gradientZ));
|
||
}
|
||
else {
|
||
size = GradientSize.createByGradient(this._initParticleSize(sizeData.gradient));
|
||
}
|
||
break;
|
||
case 1:
|
||
if (sizeData.separateAxes) {
|
||
var constantMinSeparateData = sizeData.constantMinSeparate;
|
||
var constantMaxSeparateData = sizeData.constantMaxSeparate;
|
||
size = GradientSize.createByRandomTwoConstantSeparate(new Vector3(constantMinSeparateData[0], constantMinSeparateData[1], constantMinSeparateData[2]), new Vector3(constantMaxSeparateData[0], constantMaxSeparateData[1], constantMaxSeparateData[2]));
|
||
}
|
||
else {
|
||
size = GradientSize.createByRandomTwoConstant(sizeData.constantMin, sizeData.constantMax);
|
||
}
|
||
break;
|
||
case 2:
|
||
if (sizeData.separateAxes) {
|
||
size = GradientSize.createByRandomTwoGradientSeparate(this._initParticleSize(sizeData.gradientXMin), this._initParticleSize(sizeData.gradientYMin), this._initParticleSize(sizeData.gradientZMin), this._initParticleSize(sizeData.gradientXMax), this._initParticleSize(sizeData.gradientYMax), this._initParticleSize(sizeData.gradientZMax));
|
||
}
|
||
else {
|
||
size = GradientSize.createByRandomTwoGradient(this._initParticleSize(sizeData.gradientMin), this._initParticleSize(sizeData.gradientMax));
|
||
}
|
||
break;
|
||
}
|
||
var sizeOverLifetime = new SizeOverLifetime(size);
|
||
sizeOverLifetime.enable = sizeOverLifetimeData.enable;
|
||
particleSystem.sizeOverLifetime = sizeOverLifetime;
|
||
}
|
||
var rotationOverLifetimeData = data.rotationOverLifetime;
|
||
if (rotationOverLifetimeData) {
|
||
var angularVelocityData = rotationOverLifetimeData.angularVelocity;
|
||
var angularVelocity;
|
||
switch (angularVelocityData.type) {
|
||
case 0:
|
||
if (angularVelocityData.separateAxes) {
|
||
var conSep = angularVelocityData.constantSeparate;
|
||
angularVelocity = GradientAngularVelocity.createByConstantSeparate(new Vector3(conSep[0] * anglelToRad, conSep[1] * anglelToRad, conSep[2] * anglelToRad));
|
||
}
|
||
else {
|
||
angularVelocity = GradientAngularVelocity.createByConstant(angularVelocityData.constant * anglelToRad);
|
||
}
|
||
break;
|
||
case 1:
|
||
if (angularVelocityData.separateAxes) {
|
||
angularVelocity = GradientAngularVelocity.createByGradientSeparate(this._initParticleRotation(angularVelocityData.gradientX), this._initParticleRotation(angularVelocityData.gradientY), this._initParticleRotation(angularVelocityData.gradientZ));
|
||
}
|
||
else {
|
||
angularVelocity = GradientAngularVelocity.createByGradient(this._initParticleRotation(angularVelocityData.gradient));
|
||
}
|
||
break;
|
||
case 2:
|
||
if (angularVelocityData.separateAxes) {
|
||
var minSep = angularVelocityData.constantMinSeparate;
|
||
var maxSep = angularVelocityData.constantMaxSeparate;
|
||
angularVelocity = GradientAngularVelocity.createByRandomTwoConstantSeparate(new Vector3(minSep[0] * anglelToRad, minSep[1] * anglelToRad, minSep[2] * anglelToRad), new Vector3(maxSep[0] * anglelToRad, maxSep[1] * anglelToRad, maxSep[2] * anglelToRad));
|
||
}
|
||
else {
|
||
angularVelocity = GradientAngularVelocity.createByRandomTwoConstant(angularVelocityData.constantMin * anglelToRad, angularVelocityData.constantMax * anglelToRad);
|
||
}
|
||
break;
|
||
case 3:
|
||
if (angularVelocityData.separateAxes) ;
|
||
else {
|
||
angularVelocity = GradientAngularVelocity.createByRandomTwoGradient(this._initParticleRotation(angularVelocityData.gradientMin), this._initParticleRotation(angularVelocityData.gradientMax));
|
||
}
|
||
break;
|
||
}
|
||
var rotationOverLifetime = new RotationOverLifetime(angularVelocity);
|
||
rotationOverLifetime.enable = rotationOverLifetimeData.enable;
|
||
particleSystem.rotationOverLifetime = rotationOverLifetime;
|
||
}
|
||
var textureSheetAnimationData = data.textureSheetAnimation;
|
||
if (textureSheetAnimationData) {
|
||
var frameData = textureSheetAnimationData.frame;
|
||
var frameOverTime;
|
||
switch (frameData.type) {
|
||
case 0:
|
||
frameOverTime = FrameOverTime.createByConstant(frameData.constant);
|
||
break;
|
||
case 1:
|
||
frameOverTime = FrameOverTime.createByOverTime(this._initParticleFrame(frameData.overTime));
|
||
break;
|
||
case 2:
|
||
frameOverTime = FrameOverTime.createByRandomTwoConstant(frameData.constantMin, frameData.constantMax);
|
||
break;
|
||
case 3:
|
||
frameOverTime = FrameOverTime.createByRandomTwoOverTime(this._initParticleFrame(frameData.overTimeMin), this._initParticleFrame(frameData.overTimeMax));
|
||
break;
|
||
}
|
||
var startFrameData = textureSheetAnimationData.startFrame;
|
||
var startFrame;
|
||
switch (startFrameData.type) {
|
||
case 0:
|
||
startFrame = StartFrame.createByConstant(startFrameData.constant);
|
||
break;
|
||
case 1:
|
||
startFrame = StartFrame.createByRandomTwoConstant(startFrameData.constantMin, startFrameData.constantMax);
|
||
break;
|
||
}
|
||
var textureSheetAnimation = new TextureSheetAnimation(frameOverTime, startFrame);
|
||
textureSheetAnimation.enable = textureSheetAnimationData.enable;
|
||
var tilesData = textureSheetAnimationData.tiles;
|
||
textureSheetAnimation.tiles = new Vector2(tilesData[0], tilesData[1]);
|
||
textureSheetAnimation.type = textureSheetAnimationData.type;
|
||
textureSheetAnimation.randomRow = textureSheetAnimationData.randomRow;
|
||
var rowIndex = textureSheetAnimationData.rowIndex;
|
||
(rowIndex !== undefined) && (textureSheetAnimation.rowIndex = rowIndex);
|
||
textureSheetAnimation.cycles = textureSheetAnimationData.cycles;
|
||
particleSystem.textureSheetAnimation = textureSheetAnimation;
|
||
}
|
||
}
|
||
_initParticleColor(gradientColorData) {
|
||
var gradientColor = new Gradient(4, 4);
|
||
if (!gradientColorData) {
|
||
gradientColor.addColorAlpha(0, 1);
|
||
gradientColor.addColorAlpha(1, 1);
|
||
gradientColor.addColorRGB(0, new Color(1.0, 1.0, 1.0, 1.0));
|
||
gradientColor.addColorRGB(1, new Color(1.0, 1.0, 1.0, 1.0));
|
||
}
|
||
else {
|
||
var alphasData = gradientColorData.alphas;
|
||
var i, n;
|
||
if (!alphasData) {
|
||
gradientColor.addColorAlpha(0, 1);
|
||
gradientColor.addColorAlpha(1, 1);
|
||
}
|
||
else {
|
||
for (i = 0, n = alphasData.length; i < n; i++) {
|
||
if (i == 3 && n > 4) {
|
||
i = n - 1;
|
||
console.warn("GradientDataColor warning:alpha data length is large than 4, will ignore the middle data.");
|
||
}
|
||
var alphaData = alphasData[i];
|
||
gradientColor.addColorAlpha(alphaData.key, alphaData.value);
|
||
}
|
||
}
|
||
var rgbsData = gradientColorData.rgbs;
|
||
if (!rgbsData) {
|
||
gradientColor.addColorRGB(0, new Color(1.0, 1.0, 1.0, 1.0));
|
||
gradientColor.addColorRGB(1, new Color(1.0, 1.0, 1.0, 1.0));
|
||
}
|
||
else {
|
||
for (i = 0, n = rgbsData.length; i < n; i++) {
|
||
if (i == 3 && n > 4) {
|
||
i = n - 1;
|
||
console.warn("GradientDataColor warning:rgb data length is large than 4, will ignore the middle data.");
|
||
}
|
||
var rgbData = rgbsData[i];
|
||
var rgbValue = rgbData.value;
|
||
gradientColor.addColorRGB(rgbData.key, new Color(rgbValue[0], rgbValue[1], rgbValue[2], 1.0));
|
||
}
|
||
}
|
||
}
|
||
return gradientColor;
|
||
}
|
||
_initParticleFrame(overTimeFramesData) {
|
||
var overTimeFrame = new GradientDataInt();
|
||
if (overTimeFramesData) {
|
||
var framesData = overTimeFramesData.frames;
|
||
for (var i = 0, n = framesData.length; i < n; i++) {
|
||
var frameData = framesData[i];
|
||
overTimeFrame.add(frameData.key, frameData.value);
|
||
}
|
||
}
|
||
else {
|
||
overTimeFrame.add(0, 0);
|
||
overTimeFrame.add(1, 1);
|
||
}
|
||
return overTimeFrame;
|
||
}
|
||
static _initStartLife(gradientData) {
|
||
var gradient = new GradientDataNumber();
|
||
var startLifetimesData = gradientData.startLifetimes;
|
||
for (var i = 0, n = startLifetimesData.length; i < n; i++) {
|
||
var valueData = startLifetimesData[i];
|
||
gradient.add(valueData.key, valueData.value);
|
||
}
|
||
return gradient;
|
||
}
|
||
_initParticleVelocity(gradientData) {
|
||
var gradient = new GradientDataNumber();
|
||
var velocitysData = gradientData.velocitys;
|
||
for (var i = 0, n = velocitysData.length; i < n; i++) {
|
||
var valueData = velocitysData[i];
|
||
gradient.add(valueData.key, valueData.value);
|
||
}
|
||
return gradient;
|
||
}
|
||
_initParticleSize(gradientSizeData) {
|
||
var gradientSize = new GradientDataNumber();
|
||
if (gradientSizeData) {
|
||
var sizesData = gradientSizeData.sizes;
|
||
for (var i = 0, n = sizesData.length; i < n; i++) {
|
||
var valueData = sizesData[i];
|
||
gradientSize.add(valueData.key, valueData.value);
|
||
}
|
||
}
|
||
else {
|
||
gradientSize.add(0, 0);
|
||
gradientSize.add(1, 1);
|
||
}
|
||
return gradientSize;
|
||
}
|
||
_initParticleRotation(gradientData) {
|
||
var gradient = new GradientDataNumber();
|
||
var angularVelocitysData = gradientData.angularVelocitys;
|
||
for (var i = 0, n = angularVelocitysData.length; i < n; i++) {
|
||
var valueData = angularVelocitysData[i];
|
||
gradient.add(valueData.key, valueData.value / 180.0 * Math.PI);
|
||
}
|
||
return gradient;
|
||
}
|
||
}
|
||
|
||
class SkinnedMeshSprite3DShaderDeclaration {
|
||
}
|
||
|
||
class SkinnedMeshRenderer extends MeshRenderer {
|
||
constructor(owner) {
|
||
super(owner);
|
||
this._bones = [];
|
||
this._skinnedDataLoopMarks = [];
|
||
this._localBounds = new Bounds(Vector3._ZERO, Vector3._ZERO);
|
||
this._cacheAnimationNode = [];
|
||
}
|
||
get localBounds() {
|
||
return this._localBounds;
|
||
}
|
||
set localBounds(value) {
|
||
this._localBounds = value;
|
||
}
|
||
get rootBone() {
|
||
return this._cacheRootBone;
|
||
}
|
||
set rootBone(value) {
|
||
if (this._cacheRootBone != value) {
|
||
if (this._cacheRootBone)
|
||
this._cacheRootBone.transform.off(Laya.Event.TRANSFORM_CHANGED, this, this._onWorldMatNeedChange);
|
||
else
|
||
this._owner.transform.off(Laya.Event.TRANSFORM_CHANGED, this, this._onWorldMatNeedChange);
|
||
if (value)
|
||
value.transform.on(Laya.Event.TRANSFORM_CHANGED, this, this._onWorldMatNeedChange);
|
||
else
|
||
this._owner.transform.on(Laya.Event.TRANSFORM_CHANGED, this, this._onWorldMatNeedChange);
|
||
this._cacheRootBone = value;
|
||
this._onWorldMatNeedChange(Transform3D.TRANSFORM_WORLDPOSITION | Transform3D.TRANSFORM_WORLDQUATERNION | Transform3D.TRANSFORM_WORLDSCALE);
|
||
}
|
||
}
|
||
get bones() {
|
||
return this._bones;
|
||
}
|
||
_computeSkinnedData() {
|
||
if (this._cacheMesh && this._cacheAvatar || this._cacheMesh && !this._cacheAvatar) {
|
||
var bindPoses = this._cacheMesh._inverseBindPoses;
|
||
var pathMarks = this._cacheMesh._skinnedMatrixCaches;
|
||
for (var i = 0, n = this._cacheMesh.subMeshCount; i < n; i++) {
|
||
var subMeshBoneIndices = this._cacheMesh.getSubMesh(i)._boneIndicesList;
|
||
var subData = this._skinnedData[i];
|
||
for (var j = 0, m = subMeshBoneIndices.length; j < m; j++) {
|
||
var boneIndices = subMeshBoneIndices[j];
|
||
this._computeSubSkinnedData(bindPoses, boneIndices, subData[j], pathMarks);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
_computeSubSkinnedData(bindPoses, boneIndices, data, matrixCaches) {
|
||
for (var k = 0, q = boneIndices.length; k < q; k++) {
|
||
var index = boneIndices[k];
|
||
if (this._skinnedDataLoopMarks[index] === Laya.Stat.loopCount) {
|
||
var c = matrixCaches[index];
|
||
var preData = this._skinnedData[c.subMeshIndex][c.batchIndex];
|
||
var srcIndex = c.batchBoneIndex * 16;
|
||
var dstIndex = k * 16;
|
||
for (var d = 0; d < 16; d++)
|
||
data[dstIndex + d] = preData[srcIndex + d];
|
||
}
|
||
else {
|
||
if (!this._cacheAvatar) {
|
||
Utils3D._mulMatrixArray(this._bones[index].transform.worldMatrix.elements, bindPoses[index].elements, 0, data, k * 16);
|
||
}
|
||
else {
|
||
Utils3D._mulMatrixArray(this._cacheAnimationNode[index].transform.getWorldMatrix(), bindPoses[index].elements, 0, data, k * 16);
|
||
}
|
||
this._skinnedDataLoopMarks[index] = Laya.Stat.loopCount;
|
||
}
|
||
}
|
||
}
|
||
_onWorldMatNeedChange(flag) {
|
||
this._boundsChange = true;
|
||
if (this._octreeNode) {
|
||
if (this._cacheAvatar) {
|
||
if (this._indexInOctreeMotionList === -1)
|
||
this._octreeNode._octree.addMotionObject(this);
|
||
}
|
||
else {
|
||
flag &= Transform3D.TRANSFORM_WORLDPOSITION | Transform3D.TRANSFORM_WORLDQUATERNION | Transform3D.TRANSFORM_WORLDSCALE;
|
||
if (flag) {
|
||
if (this._indexInOctreeMotionList === -1)
|
||
this._octreeNode._octree.addMotionObject(this);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
_createRenderElement() {
|
||
return new RenderElement();
|
||
}
|
||
_onMeshChange(value) {
|
||
super._onMeshChange(value);
|
||
this._cacheMesh = value;
|
||
var subMeshCount = value.subMeshCount;
|
||
this._skinnedData = [];
|
||
this._skinnedDataLoopMarks.length = value._inverseBindPoses.length;
|
||
for (var i = 0; i < subMeshCount; i++) {
|
||
var subBoneIndices = value.getSubMesh(i)._boneIndicesList;
|
||
var subCount = subBoneIndices.length;
|
||
var subData = this._skinnedData[i] = [];
|
||
for (var j = 0; j < subCount; j++)
|
||
subData[j] = new Float32Array(subBoneIndices[j].length * 16);
|
||
}
|
||
(this._cacheAvatar && value) && (this._getCacheAnimationNodes());
|
||
}
|
||
_setCacheAnimator(animator) {
|
||
this._cacheAnimator = animator;
|
||
this._shaderValues.addDefine(SkinnedMeshSprite3DShaderDeclaration.SHADERDEFINE_BONE);
|
||
this._setRootNode();
|
||
}
|
||
_calculateBoundingBox() {
|
||
if (!this._cacheAvatar) {
|
||
if (this._cacheRootBone)
|
||
this._localBounds._tranform(this._cacheRootBone.transform.worldMatrix, this._bounds);
|
||
else
|
||
this._localBounds._tranform(this._owner.transform.worldMatrix, this._bounds);
|
||
}
|
||
else {
|
||
if (this._cacheAnimator && this._rootBone) {
|
||
var worldMat = SkinnedMeshRenderer._tempMatrix4x4;
|
||
Utils3D.matrix4x4MultiplyMFM(this._cacheAnimator.owner.transform.worldMatrix, this._cacheRootAnimationNode.transform.getWorldMatrix(), worldMat);
|
||
this._localBounds._tranform(worldMat, this._bounds);
|
||
}
|
||
else {
|
||
super._calculateBoundingBox();
|
||
}
|
||
}
|
||
}
|
||
_renderUpdate(context, transform) {
|
||
if (this._cacheAnimator) {
|
||
this._computeSkinnedData();
|
||
if (!this._cacheAvatar) {
|
||
this._shaderValues.setMatrix4x4(Sprite3D.WORLDMATRIX, Matrix4x4.DEFAULT);
|
||
}
|
||
else {
|
||
var aniOwnerTrans = this._cacheAnimator.owner._transform;
|
||
this._shaderValues.setMatrix4x4(Sprite3D.WORLDMATRIX, aniOwnerTrans.worldMatrix);
|
||
}
|
||
}
|
||
else {
|
||
this._shaderValues.setMatrix4x4(Sprite3D.WORLDMATRIX, transform.worldMatrix);
|
||
}
|
||
if (!this._probReflection)
|
||
return;
|
||
if (this._reflectionMode == exports.ReflectionProbeMode.off) {
|
||
this._shaderValues.removeDefine(MeshSprite3DShaderDeclaration.SHADERDEFINE_SPECCUBE_BOX_PROJECTION);
|
||
this._shaderValues.setVector(RenderableSprite3D.REFLECTIONCUBE_HDR_PARAMS, ReflectionProbe.defaultTextureHDRDecodeValues);
|
||
this._shaderValues.setTexture(RenderableSprite3D.REFLECTIONTEXTURE, TextureCube.blackTexture);
|
||
}
|
||
else {
|
||
if (!this._probReflection.boxProjection) {
|
||
this._shaderValues.removeDefine(MeshSprite3DShaderDeclaration.SHADERDEFINE_SPECCUBE_BOX_PROJECTION);
|
||
}
|
||
else {
|
||
this._shaderValues.addDefine(MeshSprite3DShaderDeclaration.SHADERDEFINE_SPECCUBE_BOX_PROJECTION);
|
||
this._shaderValues.setVector3(RenderableSprite3D.REFLECTIONCUBE_PROBEPOSITION, this._probReflection.probePosition);
|
||
this._shaderValues.setVector3(RenderableSprite3D.REFLECTIONCUBE_PROBEBOXMAX, this._probReflection.boundsMax);
|
||
this._shaderValues.setVector3(RenderableSprite3D.REFLECTIONCUBE_PROBEBOXMIN, this._probReflection.boundsMin);
|
||
}
|
||
this._shaderValues.setTexture(RenderableSprite3D.REFLECTIONTEXTURE, this._probReflection.reflectionTexture);
|
||
this._shaderValues.setVector(RenderableSprite3D.REFLECTIONCUBE_HDR_PARAMS, this._probReflection.reflectionHDRParams);
|
||
}
|
||
}
|
||
_renderUpdateWithCamera(context, transform) {
|
||
var projectionView = context.projectionViewMatrix;
|
||
if (this._cacheAnimator) {
|
||
if (!this._cacheAvatar) {
|
||
this._shaderValues.setMatrix4x4(Sprite3D.MVPMATRIX, projectionView);
|
||
}
|
||
else {
|
||
var aniOwnerTrans = this._cacheAnimator.owner._transform;
|
||
Matrix4x4.multiply(projectionView, aniOwnerTrans.worldMatrix, this._projectionViewWorldMatrix);
|
||
this._shaderValues.setMatrix4x4(Sprite3D.MVPMATRIX, this._projectionViewWorldMatrix);
|
||
}
|
||
}
|
||
else {
|
||
Matrix4x4.multiply(projectionView, transform.worldMatrix, this._projectionViewWorldMatrix);
|
||
this._shaderValues.setMatrix4x4(Sprite3D.MVPMATRIX, this._projectionViewWorldMatrix);
|
||
}
|
||
}
|
||
_destroy() {
|
||
super._destroy();
|
||
if (!this._cacheAvatar) {
|
||
if (this._cacheRootBone)
|
||
(!this._cacheRootBone.destroyed) && (this._cacheRootBone.transform.off(Laya.Event.TRANSFORM_CHANGED, this, this._onWorldMatNeedChange));
|
||
else
|
||
(this._owner && !this._owner.destroyed) && (this._owner.transform.off(Laya.Event.TRANSFORM_CHANGED, this, this._onWorldMatNeedChange));
|
||
}
|
||
else {
|
||
if (this._cacheRootAnimationNode)
|
||
this._cacheRootAnimationNode.transform.off(Laya.Event.TRANSFORM_CHANGED, this, this._onWorldMatNeedChange);
|
||
}
|
||
}
|
||
get bounds() {
|
||
if (this._boundsChange || this._cacheAvatar) {
|
||
this._calculateBoundingBox();
|
||
this._boundsChange = false;
|
||
}
|
||
return this._bounds;
|
||
}
|
||
_setRootBone(name) {
|
||
this._rootBone = name;
|
||
this._setRootNode();
|
||
}
|
||
_setRootNode() {
|
||
var rootNode;
|
||
if (this._cacheAnimator && this._rootBone && this._cacheAvatar)
|
||
rootNode = this._cacheAnimator._avatarNodeMap[this._rootBone];
|
||
else
|
||
rootNode = null;
|
||
if (this._cacheRootAnimationNode != rootNode) {
|
||
this._onWorldMatNeedChange(Transform3D.TRANSFORM_WORLDPOSITION | Transform3D.TRANSFORM_WORLDQUATERNION | Transform3D.TRANSFORM_WORLDSCALE);
|
||
this._owner.transform.off(Laya.Event.TRANSFORM_CHANGED, this, this._onWorldMatNeedChange);
|
||
if (this._cacheRootAnimationNode)
|
||
this._cacheRootAnimationNode.transform.off(Laya.Event.TRANSFORM_CHANGED, this, this._onWorldMatNeedChange);
|
||
(rootNode) && (rootNode.transform.on(Laya.Event.TRANSFORM_CHANGED, this, this._onWorldMatNeedChange));
|
||
this._cacheRootAnimationNode = rootNode;
|
||
}
|
||
}
|
||
_getCacheAnimationNodes() {
|
||
var meshBoneNames = this._cacheMesh._boneNames;
|
||
var innerBindPoseCount = this._cacheMesh._inverseBindPoses.length;
|
||
this._cacheAnimationNode.length = innerBindPoseCount;
|
||
var nodeMap = this._cacheAnimator._avatarNodeMap;
|
||
for (var i = 0; i < innerBindPoseCount; i++) {
|
||
var node = nodeMap[meshBoneNames[i]];
|
||
this._cacheAnimationNode[i] = node;
|
||
}
|
||
}
|
||
_setCacheAvatar(value) {
|
||
if (this._cacheAvatar !== value) {
|
||
if (this._cacheMesh) {
|
||
this._cacheAvatar = value;
|
||
if (value) {
|
||
this._shaderValues.addDefine(SkinnedMeshSprite3DShaderDeclaration.SHADERDEFINE_BONE);
|
||
this._getCacheAnimationNodes();
|
||
}
|
||
}
|
||
else {
|
||
this._cacheAvatar = value;
|
||
}
|
||
this._setRootNode();
|
||
}
|
||
}
|
||
}
|
||
SkinnedMeshRenderer._tempMatrix4x4 = new Matrix4x4();
|
||
|
||
class SkinnedMeshSprite3D extends RenderableSprite3D {
|
||
constructor(mesh = null, name = null) {
|
||
super(name);
|
||
this._meshFilter = new MeshFilter(this);
|
||
this._render = new SkinnedMeshRenderer(this);
|
||
(mesh) && (this._meshFilter.sharedMesh = mesh);
|
||
}
|
||
static __init__() {
|
||
SkinnedMeshSprite3DShaderDeclaration.SHADERDEFINE_BONE = Shader3D.getDefineByName("BONE");
|
||
SkinnedMeshSprite3DShaderDeclaration.SHADERDEFINE_SIMPLEBONE = Shader3D.getDefineByName("SIMPLEBONE");
|
||
}
|
||
get meshFilter() {
|
||
return this._meshFilter;
|
||
}
|
||
get skinnedMeshRenderer() {
|
||
return this._render;
|
||
}
|
||
_parse(data, spriteMap) {
|
||
super._parse(data, spriteMap);
|
||
var render = this.skinnedMeshRenderer;
|
||
var lightmapIndex = data.lightmapIndex;
|
||
(lightmapIndex != null) && (render.lightmapIndex = lightmapIndex);
|
||
var lightmapScaleOffsetArray = data.lightmapScaleOffset;
|
||
(lightmapScaleOffsetArray) && (render.lightmapScaleOffset = new Vector4(lightmapScaleOffsetArray[0], lightmapScaleOffsetArray[1], lightmapScaleOffsetArray[2], lightmapScaleOffsetArray[3]));
|
||
(data.enableRender != undefined) && (render.enable = data.enableRender);
|
||
(data.receiveShadows != undefined) && (render.receiveShadow = data.receiveShadows);
|
||
(data.castShadow != undefined) && (render.castShadow = data.castShadow);
|
||
var meshPath;
|
||
meshPath = data.meshPath;
|
||
if (meshPath) {
|
||
var mesh = Laya.Loader.getRes(meshPath);
|
||
(mesh) && (this.meshFilter.sharedMesh = mesh);
|
||
}
|
||
var materials = data.materials;
|
||
if (materials) {
|
||
var sharedMaterials = render.sharedMaterials;
|
||
var materialCount = materials.length;
|
||
sharedMaterials.length = materialCount;
|
||
for (var i = 0; i < materialCount; i++) {
|
||
sharedMaterials[i] = Laya.Loader.getRes(materials[i].path);
|
||
}
|
||
render.sharedMaterials = sharedMaterials;
|
||
}
|
||
var boundBox = data.boundBox;
|
||
var min = boundBox.min;
|
||
var max = boundBox.max;
|
||
render.localBounds.setMin(new Vector3(min[0], min[1], min[2]));
|
||
render.localBounds.setMax(new Vector3(max[0], max[1], max[2]));
|
||
if (spriteMap) {
|
||
var rootBoneData = data.rootBone;
|
||
render.rootBone = spriteMap[rootBoneData];
|
||
var bonesData = data.bones;
|
||
var n;
|
||
for (i = 0, n = bonesData.length; i < n; i++)
|
||
render.bones.push(spriteMap[bonesData[i]]);
|
||
}
|
||
else {
|
||
(data.rootBone) && (render._setRootBone(data.rootBone));
|
||
}
|
||
}
|
||
_changeHierarchyAnimator(animator) {
|
||
super._changeHierarchyAnimator(animator);
|
||
this.skinnedMeshRenderer._setCacheAnimator(animator);
|
||
}
|
||
_changeAnimatorAvatar(avatar) {
|
||
this.skinnedMeshRenderer._setCacheAvatar(avatar);
|
||
}
|
||
_cloneTo(destObject, srcRoot, dstRoot) {
|
||
var meshSprite3D = destObject;
|
||
meshSprite3D.meshFilter.sharedMesh = this.meshFilter.sharedMesh;
|
||
var meshRender = this._render;
|
||
var destMeshRender = meshSprite3D._render;
|
||
destMeshRender.enable = meshRender.enable;
|
||
destMeshRender.sharedMaterials = meshRender.sharedMaterials;
|
||
destMeshRender.castShadow = meshRender.castShadow;
|
||
var lightmapScaleOffset = meshRender.lightmapScaleOffset;
|
||
lightmapScaleOffset && (destMeshRender.lightmapScaleOffset = lightmapScaleOffset.clone());
|
||
destMeshRender.receiveShadow = meshRender.receiveShadow;
|
||
destMeshRender.sortingFudge = meshRender.sortingFudge;
|
||
destMeshRender._rootBone = meshRender._rootBone;
|
||
var bones = meshRender.bones;
|
||
var destBones = destMeshRender.bones;
|
||
var bonesCount = bones.length;
|
||
destBones.length = bonesCount;
|
||
var rootBone = meshRender.rootBone;
|
||
if (rootBone) {
|
||
var pathes = Utils3D._getHierarchyPath(srcRoot, rootBone, SkinnedMeshSprite3D._tempArray0);
|
||
if (pathes)
|
||
destMeshRender.rootBone = Utils3D._getNodeByHierarchyPath(dstRoot, pathes);
|
||
else
|
||
destMeshRender.rootBone = rootBone;
|
||
}
|
||
for (var i = 0; i < bones.length; i++) {
|
||
pathes = Utils3D._getHierarchyPath(srcRoot, bones[i], SkinnedMeshSprite3D._tempArray0);
|
||
if (pathes)
|
||
destBones[i] = Utils3D._getNodeByHierarchyPath(dstRoot, pathes);
|
||
else
|
||
destBones[i] = bones[i];
|
||
}
|
||
var lbb = meshRender.localBounds;
|
||
(lbb) && (lbb.cloneTo(destMeshRender.localBounds));
|
||
super._cloneTo(destObject, srcRoot, dstRoot);
|
||
}
|
||
destroy(destroyChild = true) {
|
||
if (this.destroyed)
|
||
return;
|
||
super.destroy(destroyChild);
|
||
this._meshFilter.destroy();
|
||
}
|
||
_create() {
|
||
return new SkinnedMeshSprite3D();
|
||
}
|
||
}
|
||
SkinnedMeshSprite3D._tempArray0 = [];
|
||
SkinnedMeshSprite3D.BONES = Shader3D.propertyNameToID("u_Bones");
|
||
SkinnedMeshSprite3D.SIMPLE_SIMPLEANIMATORTEXTURE = Shader3D.propertyNameToID("u_SimpleAnimatorTexture");
|
||
SkinnedMeshSprite3D.SIMPLE_SIMPLEANIMATORPARAMS = Shader3D.propertyNameToID("u_SimpleAnimatorParams");
|
||
SkinnedMeshSprite3D.SIMPLE_SIMPLEANIMATORTEXTURESIZE = Shader3D.propertyNameToID("u_SimpleAnimatorTextureSize");
|
||
|
||
class TrailMaterial extends Material {
|
||
constructor() {
|
||
super();
|
||
this.setShaderName("Trail");
|
||
this._color = new Vector4(1.0, 1.0, 1.0, 1.0);
|
||
this._shaderValues.setVector(TrailMaterial.TILINGOFFSET, new Vector4(1.0, 1.0, 0.0, 0.0));
|
||
this._shaderValues.setVector(TrailMaterial.TINTCOLOR, new Vector4(1.0, 1.0, 1.0, 1.0));
|
||
this.renderMode = TrailMaterial.RENDERMODE_ALPHABLENDED;
|
||
}
|
||
static __initDefine__() {
|
||
TrailMaterial.SHADERDEFINE_MAINTEXTURE = Shader3D.getDefineByName("MAINTEXTURE");
|
||
TrailMaterial.SHADERDEFINE_ADDTIVEFOG = Shader3D.getDefineByName("ADDTIVEFOG");
|
||
}
|
||
get _TintColorR() {
|
||
return this._color.x;
|
||
}
|
||
set _TintColorR(value) {
|
||
this._color.x = value;
|
||
this.color = this._color;
|
||
}
|
||
get _TintColorG() {
|
||
return this._color.y;
|
||
}
|
||
set _TintColorG(value) {
|
||
this._color.y = value;
|
||
this.color = this._color;
|
||
}
|
||
get _TintColorB() {
|
||
return this._color.z;
|
||
}
|
||
set _TintColorB(value) {
|
||
this._color.z = value;
|
||
this.color = this._color;
|
||
}
|
||
get _TintColorA() {
|
||
return this._color.w;
|
||
}
|
||
set _TintColorA(value) {
|
||
this._color.w = value;
|
||
this.color = this._color;
|
||
}
|
||
get _MainTex_STX() {
|
||
return this._shaderValues.getVector(TrailMaterial.TILINGOFFSET).x;
|
||
}
|
||
set _MainTex_STX(x) {
|
||
var tilOff = this._shaderValues.getVector(TrailMaterial.TILINGOFFSET);
|
||
tilOff.x = x;
|
||
this.tilingOffset = tilOff;
|
||
}
|
||
get _MainTex_STY() {
|
||
return this._shaderValues.getVector(TrailMaterial.TILINGOFFSET).y;
|
||
}
|
||
set _MainTex_STY(y) {
|
||
var tilOff = this._shaderValues.getVector(TrailMaterial.TILINGOFFSET);
|
||
tilOff.y = y;
|
||
this.tilingOffset = tilOff;
|
||
}
|
||
get _MainTex_STZ() {
|
||
return this._shaderValues.getVector(TrailMaterial.TILINGOFFSET).z;
|
||
}
|
||
set _MainTex_STZ(z) {
|
||
var tilOff = this._shaderValues.getVector(TrailMaterial.TILINGOFFSET);
|
||
tilOff.z = z;
|
||
this.tilingOffset = tilOff;
|
||
}
|
||
get _MainTex_STW() {
|
||
return this._shaderValues.getVector(TrailMaterial.TILINGOFFSET).w;
|
||
}
|
||
set _MainTex_STW(w) {
|
||
var tilOff = this._shaderValues.getVector(TrailMaterial.TILINGOFFSET);
|
||
tilOff.w = w;
|
||
this.tilingOffset = tilOff;
|
||
}
|
||
set renderMode(value) {
|
||
switch (value) {
|
||
case TrailMaterial.RENDERMODE_ADDTIVE:
|
||
this.renderQueue = Material.RENDERQUEUE_TRANSPARENT;
|
||
this.alphaTest = false;
|
||
this.depthWrite = false;
|
||
this.cull = RenderState.CULL_NONE;
|
||
this.blend = RenderState.BLEND_ENABLE_ALL;
|
||
this.blendSrc = RenderState.BLENDPARAM_SRC_ALPHA;
|
||
this.blendDst = RenderState.BLENDPARAM_ONE;
|
||
this.depthTest = RenderState.DEPTHTEST_LESS;
|
||
this._shaderValues.addDefine(TrailMaterial.SHADERDEFINE_ADDTIVEFOG);
|
||
break;
|
||
case TrailMaterial.RENDERMODE_ALPHABLENDED:
|
||
this.renderQueue = Material.RENDERQUEUE_TRANSPARENT;
|
||
this.alphaTest = false;
|
||
this.depthWrite = false;
|
||
this.cull = RenderState.CULL_NONE;
|
||
this.blend = RenderState.BLEND_ENABLE_ALL;
|
||
this.blendSrc = RenderState.BLENDPARAM_SRC_ALPHA;
|
||
this.blendDst = RenderState.BLENDPARAM_ONE_MINUS_SRC_ALPHA;
|
||
this.depthTest = RenderState.DEPTHTEST_LESS;
|
||
this._shaderValues.removeDefine(TrailMaterial.SHADERDEFINE_ADDTIVEFOG);
|
||
break;
|
||
default:
|
||
throw new Error("TrailMaterial : renderMode value error.");
|
||
}
|
||
}
|
||
get colorR() {
|
||
return this._TintColorR;
|
||
}
|
||
set colorR(value) {
|
||
this._TintColorR = value;
|
||
}
|
||
get colorG() {
|
||
return this._TintColorG;
|
||
}
|
||
set colorG(value) {
|
||
this._TintColorG = value;
|
||
}
|
||
get colorB() {
|
||
return this._TintColorB;
|
||
}
|
||
set colorB(value) {
|
||
this._TintColorB = value;
|
||
}
|
||
get colorA() {
|
||
return this._TintColorA;
|
||
}
|
||
set colorA(value) {
|
||
this._TintColorA = value;
|
||
}
|
||
get color() {
|
||
return this._shaderValues.getVector(TrailMaterial.TINTCOLOR);
|
||
}
|
||
set color(value) {
|
||
this._shaderValues.setVector(TrailMaterial.TINTCOLOR, value);
|
||
}
|
||
get texture() {
|
||
return this._shaderValues.getTexture(TrailMaterial.MAINTEXTURE);
|
||
}
|
||
set texture(value) {
|
||
if (value)
|
||
this._shaderValues.addDefine(TrailMaterial.SHADERDEFINE_MAINTEXTURE);
|
||
else
|
||
this._shaderValues.removeDefine(TrailMaterial.SHADERDEFINE_MAINTEXTURE);
|
||
this._shaderValues.setTexture(TrailMaterial.MAINTEXTURE, value);
|
||
}
|
||
get tilingOffsetX() {
|
||
return this._MainTex_STX;
|
||
}
|
||
set tilingOffsetX(x) {
|
||
this._MainTex_STX = x;
|
||
}
|
||
get tilingOffsetY() {
|
||
return this._MainTex_STY;
|
||
}
|
||
set tilingOffsetY(y) {
|
||
this._MainTex_STY = y;
|
||
}
|
||
get tilingOffsetZ() {
|
||
return this._MainTex_STZ;
|
||
}
|
||
set tilingOffsetZ(z) {
|
||
this._MainTex_STZ = z;
|
||
}
|
||
get tilingOffsetW() {
|
||
return this._MainTex_STW;
|
||
}
|
||
set tilingOffsetW(w) {
|
||
this._MainTex_STW = w;
|
||
}
|
||
get tilingOffset() {
|
||
return this._shaderValues.getVector(TrailMaterial.TILINGOFFSET);
|
||
}
|
||
set tilingOffset(value) {
|
||
if (value) {
|
||
this._shaderValues.setVector(TrailMaterial.TILINGOFFSET, value);
|
||
}
|
||
else {
|
||
this._shaderValues.getVector(TrailMaterial.TILINGOFFSET).setValue(1.0, 1.0, 0.0, 0.0);
|
||
}
|
||
}
|
||
clone() {
|
||
var dest = new TrailMaterial();
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
}
|
||
TrailMaterial.RENDERMODE_ALPHABLENDED = 0;
|
||
TrailMaterial.RENDERMODE_ADDTIVE = 1;
|
||
TrailMaterial.MAINTEXTURE = Shader3D.propertyNameToID("u_MainTexture");
|
||
TrailMaterial.TINTCOLOR = Shader3D.propertyNameToID("u_MainColor");
|
||
TrailMaterial.TILINGOFFSET = Shader3D.propertyNameToID("u_TilingOffset");
|
||
|
||
class TextureMode {
|
||
}
|
||
TextureMode.Stretch = 0;
|
||
TextureMode.Tile = 1;
|
||
|
||
(function (TrailAlignment) {
|
||
TrailAlignment[TrailAlignment["View"] = 0] = "View";
|
||
TrailAlignment[TrailAlignment["TransformZ"] = 1] = "TransformZ";
|
||
})(exports.TrailAlignment || (exports.TrailAlignment = {}));
|
||
|
||
class VertexTrail {
|
||
static get vertexDeclaration1() {
|
||
return VertexTrail._vertexDeclaration1;
|
||
}
|
||
static get vertexDeclaration2() {
|
||
return VertexTrail._vertexDeclaration2;
|
||
}
|
||
get vertexDeclaration() {
|
||
return VertexTrail._vertexDeclaration1;
|
||
}
|
||
static __init__() {
|
||
VertexTrail._vertexDeclaration1 = new VertexDeclaration(32, [new VertexElement(0, VertexElementFormat.Vector3, VertexTrail.TRAIL_POSITION0),
|
||
new VertexElement(12, VertexElementFormat.Vector3, VertexTrail.TRAIL_OFFSETVECTOR),
|
||
new VertexElement(24, VertexElementFormat.Single, VertexTrail.TRAIL_TIME0),
|
||
new VertexElement(28, VertexElementFormat.Single, VertexTrail.TRAIL_TEXTURECOORDINATE0Y)]);
|
||
VertexTrail._vertexDeclaration2 = new VertexDeclaration(20, [new VertexElement(0, VertexElementFormat.Single, VertexTrail.TRAIL_TEXTURECOORDINATE0X),
|
||
new VertexElement(4, VertexElementFormat.Color, VertexTrail.TRAIL_COLOR)]);
|
||
}
|
||
}
|
||
VertexTrail.TRAIL_POSITION0 = 0;
|
||
VertexTrail.TRAIL_OFFSETVECTOR = 1;
|
||
VertexTrail.TRAIL_TIME0 = 2;
|
||
VertexTrail.TRAIL_TEXTURECOORDINATE0Y = 3;
|
||
VertexTrail.TRAIL_TEXTURECOORDINATE0X = 4;
|
||
VertexTrail.TRAIL_COLOR = 5;
|
||
|
||
class TrailGeometry extends GeometryElement {
|
||
constructor(owner) {
|
||
super();
|
||
this._floatCountPerVertices1 = 8;
|
||
this._floatCountPerVertices2 = 5;
|
||
this._increaseSegementCount = 16;
|
||
this._activeIndex = 0;
|
||
this._endIndex = 0;
|
||
this._needAddFirstVertex = false;
|
||
this._isTempEndVertex = false;
|
||
this._vertices1 = null;
|
||
this._vertices2 = null;
|
||
this._lastFixedVertexPosition = new Vector3();
|
||
this._bufferState = new BufferState();
|
||
this.tmpColor = new Color();
|
||
this._disappearBoundsMode = false;
|
||
this._owner = owner;
|
||
this._segementCount = this._increaseSegementCount;
|
||
this._resizeData(this._segementCount, this._bufferState);
|
||
var bounds = this._owner._owner.trailRenderer.bounds;
|
||
var sprite3dPosition = this._owner._owner.transform.position;
|
||
bounds.setMin(sprite3dPosition);
|
||
bounds.setMax(sprite3dPosition);
|
||
}
|
||
_resizeData(segementCount, bufferState) {
|
||
this._subBirthTime = new Float32Array(segementCount);
|
||
this._subDistance = new Float64Array(segementCount);
|
||
var gl = Laya.LayaGL.instance;
|
||
var vertexCount = segementCount * 2;
|
||
var vertexDeclaration1 = VertexTrail.vertexDeclaration1;
|
||
var vertexDeclaration2 = VertexTrail.vertexDeclaration2;
|
||
var vertexBuffers = [];
|
||
var vertexbuffer1Size = vertexCount * vertexDeclaration1.vertexStride;
|
||
var vertexbuffer2Size = vertexCount * vertexDeclaration2.vertexStride;
|
||
var memorySize = vertexbuffer1Size + vertexbuffer2Size;
|
||
this._vertices1 = new Float32Array(vertexCount * this._floatCountPerVertices1);
|
||
this._vertices2 = new Float32Array(vertexCount * this._floatCountPerVertices2);
|
||
this._vertexBuffer1 = new VertexBuffer3D(vertexbuffer1Size, gl.STATIC_DRAW, false);
|
||
this._vertexBuffer1.vertexDeclaration = vertexDeclaration1;
|
||
this._vertexBuffer2 = new VertexBuffer3D(vertexbuffer2Size, gl.DYNAMIC_DRAW, false);
|
||
this._vertexBuffer2.vertexDeclaration = vertexDeclaration2;
|
||
vertexBuffers.push(this._vertexBuffer1);
|
||
vertexBuffers.push(this._vertexBuffer2);
|
||
bufferState.bind();
|
||
bufferState.applyVertexBuffers(vertexBuffers);
|
||
bufferState.unBind();
|
||
Laya.Resource._addMemory(memorySize, memorySize);
|
||
}
|
||
_resetData() {
|
||
var count = this._endIndex - this._activeIndex;
|
||
var oldVertices1 = new Float32Array(this._vertices1.buffer, this._floatCountPerVertices1 * 2 * this._activeIndex * 4, this._floatCountPerVertices1 * 2 * count);
|
||
var oldVertices2 = new Float32Array(this._vertices2.buffer, this._floatCountPerVertices2 * 2 * this._activeIndex * 4, this._floatCountPerVertices2 * 2 * count);
|
||
var oldSubDistance = new Float64Array(this._subDistance.buffer, this._activeIndex * 8, count);
|
||
var oldSubBirthTime = new Float32Array(this._subBirthTime.buffer, this._activeIndex * 4, count);
|
||
if (count === this._segementCount) {
|
||
var memorySize = this._vertexBuffer1._byteLength + this._vertexBuffer2._byteLength;
|
||
Laya.Resource._addMemory(-memorySize, -memorySize);
|
||
this._vertexBuffer1.destroy();
|
||
this._vertexBuffer2.destroy();
|
||
this._segementCount += this._increaseSegementCount;
|
||
this._resizeData(this._segementCount, this._bufferState);
|
||
}
|
||
this._vertices1.set(oldVertices1, 0);
|
||
this._vertices2.set(oldVertices2, 0);
|
||
this._subDistance.set(oldSubDistance, 0);
|
||
this._subBirthTime.set(oldSubBirthTime, 0);
|
||
this._endIndex = count;
|
||
this._activeIndex = 0;
|
||
this._vertexBuffer1.setData(this._vertices1.buffer, 0, this._floatCountPerVertices1 * 2 * this._activeIndex * 4, this._floatCountPerVertices1 * 2 * count * 4);
|
||
this._vertexBuffer2.setData(this._vertices2.buffer, 0, this._floatCountPerVertices2 * 2 * this._activeIndex * 4, this._floatCountPerVertices2 * 2 * count * 4);
|
||
}
|
||
_updateTrail(camera, lastPosition, position) {
|
||
if (!Vector3.equals(lastPosition, position)) {
|
||
if ((this._endIndex - this._activeIndex) === 0)
|
||
this._addTrailByFirstPosition(camera, position);
|
||
else
|
||
this._addTrailByNextPosition(camera, position);
|
||
}
|
||
}
|
||
_addTrailByFirstPosition(camera, position) {
|
||
(this._endIndex === this._segementCount) && (this._resetData());
|
||
this._subDistance[this._endIndex] = 0;
|
||
this._subBirthTime[this._endIndex] = this._owner._curtime;
|
||
this._endIndex++;
|
||
position.cloneTo(this._lastFixedVertexPosition);
|
||
this._needAddFirstVertex = true;
|
||
}
|
||
_addTrailByNextPosition(camera, position) {
|
||
var delVector3 = TrailGeometry._tempVector30;
|
||
var pointAtoBVector3 = TrailGeometry._tempVector31;
|
||
switch (this._owner.alignment) {
|
||
case exports.TrailAlignment.View:
|
||
var cameraMatrix = camera.viewMatrix;
|
||
Vector3.transformCoordinate(position, cameraMatrix, TrailGeometry._tempVector33);
|
||
Vector3.transformCoordinate(this._lastFixedVertexPosition, cameraMatrix, TrailGeometry._tempVector34);
|
||
Vector3.subtract(TrailGeometry._tempVector33, TrailGeometry._tempVector34, delVector3);
|
||
Vector3.cross(TrailGeometry._tempVector33, delVector3, pointAtoBVector3);
|
||
break;
|
||
case exports.TrailAlignment.TransformZ:
|
||
Vector3.subtract(position, this._lastFixedVertexPosition, delVector3);
|
||
var forward = TrailGeometry._tempVector32;
|
||
this._owner._owner.transform.getForward(forward);
|
||
Vector3.cross(delVector3, forward, pointAtoBVector3);
|
||
break;
|
||
}
|
||
Vector3.normalize(pointAtoBVector3, pointAtoBVector3);
|
||
Vector3.scale(pointAtoBVector3, this._owner.widthMultiplier / 2, pointAtoBVector3);
|
||
var delLength = Vector3.scalarLength(delVector3);
|
||
var tempEndIndex;
|
||
var offset;
|
||
if (this._needAddFirstVertex) {
|
||
this._updateVerticesByPositionData(position, pointAtoBVector3, this._endIndex - 1);
|
||
this._needAddFirstVertex = false;
|
||
}
|
||
if (delLength - this._owner.minVertexDistance >= MathUtils3D.zeroTolerance) {
|
||
if (this._isTempEndVertex) {
|
||
tempEndIndex = this._endIndex - 1;
|
||
offset = delLength - this._subDistance[tempEndIndex];
|
||
this._updateVerticesByPosition(position, pointAtoBVector3, delLength, tempEndIndex);
|
||
this._owner._totalLength += offset;
|
||
}
|
||
else {
|
||
(this._endIndex === this._segementCount) && (this._resetData());
|
||
this._updateVerticesByPosition(position, pointAtoBVector3, delLength, this._endIndex);
|
||
this._owner._totalLength += delLength;
|
||
this._endIndex++;
|
||
}
|
||
position.cloneTo(this._lastFixedVertexPosition);
|
||
this._isTempEndVertex = false;
|
||
}
|
||
else {
|
||
if (this._isTempEndVertex) {
|
||
tempEndIndex = this._endIndex - 1;
|
||
offset = delLength - this._subDistance[tempEndIndex];
|
||
this._updateVerticesByPosition(position, pointAtoBVector3, delLength, tempEndIndex);
|
||
this._owner._totalLength += offset;
|
||
}
|
||
else {
|
||
(this._endIndex === this._segementCount) && (this._resetData());
|
||
this._updateVerticesByPosition(position, pointAtoBVector3, delLength, this._endIndex);
|
||
this._owner._totalLength += delLength;
|
||
this._endIndex++;
|
||
}
|
||
this._isTempEndVertex = true;
|
||
}
|
||
}
|
||
_updateVerticesByPositionData(position, pointAtoBVector3, index) {
|
||
var vertexOffset = this._floatCountPerVertices1 * 2 * index;
|
||
var curtime = this._owner._curtime;
|
||
this._vertices1[vertexOffset] = position.x;
|
||
this._vertices1[vertexOffset + 1] = position.y;
|
||
this._vertices1[vertexOffset + 2] = position.z;
|
||
this._vertices1[vertexOffset + 3] = -pointAtoBVector3.x;
|
||
this._vertices1[vertexOffset + 4] = -pointAtoBVector3.y;
|
||
this._vertices1[vertexOffset + 5] = -pointAtoBVector3.z;
|
||
this._vertices1[vertexOffset + 6] = curtime;
|
||
this._vertices1[vertexOffset + 7] = 1.0;
|
||
this._vertices1[vertexOffset + 8] = position.x;
|
||
this._vertices1[vertexOffset + 9] = position.y;
|
||
this._vertices1[vertexOffset + 10] = position.z;
|
||
this._vertices1[vertexOffset + 11] = pointAtoBVector3.x;
|
||
this._vertices1[vertexOffset + 12] = pointAtoBVector3.y;
|
||
this._vertices1[vertexOffset + 13] = pointAtoBVector3.z;
|
||
this._vertices1[vertexOffset + 14] = curtime;
|
||
this._vertices1[vertexOffset + 15] = 0.0;
|
||
var bounds = this._owner._owner.trailRenderer.bounds;
|
||
var min = bounds.getMin();
|
||
var max = bounds.getMax();
|
||
var up = TrailGeometry._tempVector35;
|
||
var down = TrailGeometry._tempVector36;
|
||
var out = TrailGeometry._tempVector32;
|
||
Vector3.add(position, pointAtoBVector3, up);
|
||
Vector3.subtract(position, pointAtoBVector3, down);
|
||
Vector3.min(down, up, out);
|
||
Vector3.min(min, out, min);
|
||
bounds.setMin(min);
|
||
Vector3.max(up, down, out);
|
||
Vector3.max(max, out, max);
|
||
bounds.setMax(max);
|
||
var floatCount = this._floatCountPerVertices1 * 2;
|
||
this._vertexBuffer1.setData(this._vertices1.buffer, vertexOffset * 4, vertexOffset * 4, floatCount * 4);
|
||
}
|
||
_updateVerticesByPosition(position, pointAtoBVector3, delDistance, index) {
|
||
this._updateVerticesByPositionData(position, pointAtoBVector3, index);
|
||
this._subDistance[index] = delDistance;
|
||
this._subBirthTime[index] = this._owner._curtime;
|
||
}
|
||
_updateVertexBufferUV() {
|
||
var bounds;
|
||
var min, max;
|
||
if (this._disappearBoundsMode) {
|
||
bounds = this._owner._owner.trailRenderer.bounds;
|
||
var sprite3dPosition = this._owner._owner.transform.position;
|
||
bounds.setMin(sprite3dPosition);
|
||
bounds.setMax(sprite3dPosition);
|
||
min = bounds.getMin();
|
||
max = bounds.getMax();
|
||
}
|
||
var vertexCount = this._endIndex;
|
||
var curLength = 0;
|
||
var gradient = this._owner.colorGradient;
|
||
var startAlphaIndex = gradient.colorAlphaKeysCount - 1;
|
||
var startColorIndex = gradient.colorRGBKeysCount - 1;
|
||
var totalLength = this._owner._totalLength;
|
||
var stride = this._floatCountPerVertices2 * 2;
|
||
for (var i = this._activeIndex; i < vertexCount; i++) {
|
||
(i !== this._activeIndex) && (curLength += this._subDistance[i]);
|
||
var uvX;
|
||
var lerpFactor;
|
||
if (this._owner.textureMode == TextureMode.Stretch) {
|
||
uvX = 1.0 - curLength / totalLength;
|
||
lerpFactor = uvX;
|
||
}
|
||
else {
|
||
lerpFactor = 1.0 - curLength / totalLength;
|
||
uvX = 1.0 - (totalLength - curLength);
|
||
}
|
||
startColorIndex = gradient.evaluateColorRGB(lerpFactor, this.tmpColor, startColorIndex, true);
|
||
startAlphaIndex = gradient.evaluateColorAlpha(lerpFactor, this.tmpColor, startAlphaIndex, true);
|
||
var index = i * stride;
|
||
this._vertices2[index + 0] = uvX;
|
||
this._vertices2[index + 1] = this.tmpColor.r;
|
||
this._vertices2[index + 2] = this.tmpColor.g;
|
||
this._vertices2[index + 3] = this.tmpColor.b;
|
||
this._vertices2[index + 4] = this.tmpColor.a;
|
||
this._vertices2[index + 5] = uvX;
|
||
this._vertices2[index + 6] = this.tmpColor.r;
|
||
this._vertices2[index + 7] = this.tmpColor.g;
|
||
this._vertices2[index + 8] = this.tmpColor.b;
|
||
this._vertices2[index + 9] = this.tmpColor.a;
|
||
if (this._disappearBoundsMode) {
|
||
var posOffset = this._floatCountPerVertices1 * 2 * i;
|
||
var pos = TrailGeometry._tempVector32;
|
||
var up = TrailGeometry._tempVector33;
|
||
var side = TrailGeometry._tempVector34;
|
||
pos.setValue(this._vertices1[posOffset + 0], this._vertices1[posOffset + 1], this._vertices1[posOffset + 2]);
|
||
up.setValue(this._vertices1[posOffset + 3], this._vertices1[posOffset + 4], this._vertices1[posOffset + 5]);
|
||
Vector3.add(pos, up, side);
|
||
Vector3.min(side, min, min);
|
||
Vector3.max(side, max, max);
|
||
Vector3.subtract(pos, up, side);
|
||
Vector3.min(side, min, min);
|
||
Vector3.max(side, max, max);
|
||
}
|
||
}
|
||
if (this._disappearBoundsMode) {
|
||
bounds.setMin(min);
|
||
bounds.setMax(max);
|
||
this._disappearBoundsMode = false;
|
||
}
|
||
var offset = this._activeIndex * stride;
|
||
this._vertexBuffer2.setData(this._vertices2.buffer, offset * 4, offset * 4, (vertexCount * stride - offset) * 4);
|
||
}
|
||
_updateDisappear() {
|
||
var count = this._endIndex;
|
||
for (var i = this._activeIndex; i < count; i++) {
|
||
if (this._owner._curtime - this._subBirthTime[i] >= this._owner.time + MathUtils3D.zeroTolerance) {
|
||
var nextIndex = i + 1;
|
||
if (nextIndex !== count)
|
||
this._owner._totalLength -= this._subDistance[nextIndex];
|
||
if (this._isTempEndVertex && (nextIndex === count - 1)) {
|
||
var fixedPos = this._lastFixedVertexPosition;
|
||
fixedPos.x = this._vertices1[0];
|
||
fixedPos.y = this._vertices1[1];
|
||
fixedPos.z = this._vertices1[2];
|
||
this._isTempEndVertex = false;
|
||
}
|
||
this._activeIndex++;
|
||
this._disappearBoundsMode = true;
|
||
}
|
||
else {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
_getType() {
|
||
return TrailGeometry._type;
|
||
}
|
||
_prepareRender(state) {
|
||
return this._endIndex - this._activeIndex > 1;
|
||
}
|
||
_render(state) {
|
||
this._bufferState.bind();
|
||
var gl = Laya.LayaGL.instance;
|
||
var start = this._activeIndex * 2;
|
||
var count = this._endIndex * 2 - start;
|
||
gl.drawArrays(gl.TRIANGLE_STRIP, start, count);
|
||
Laya.Stat.renderBatches++;
|
||
Laya.Stat.trianglesFaces += count - 2;
|
||
}
|
||
destroy() {
|
||
super.destroy();
|
||
var memorySize = this._vertexBuffer1._byteLength + this._vertexBuffer2._byteLength;
|
||
Laya.Resource._addMemory(-memorySize, -memorySize);
|
||
this._bufferState.destroy();
|
||
this._vertexBuffer1.destroy();
|
||
this._vertexBuffer2.destroy();
|
||
this._bufferState = null;
|
||
this._vertices1 = null;
|
||
this._vertexBuffer1 = null;
|
||
this._vertices2 = null;
|
||
this._vertexBuffer2 = null;
|
||
this._subBirthTime = null;
|
||
this._subDistance = null;
|
||
this._lastFixedVertexPosition = null;
|
||
this._disappearBoundsMode = false;
|
||
}
|
||
clear() {
|
||
this._activeIndex = 0;
|
||
this._endIndex = 0;
|
||
this._disappearBoundsMode = false;
|
||
this._subBirthTime.fill(0);
|
||
this._subDistance.fill(0);
|
||
this._segementCount = 0;
|
||
this._isTempEndVertex = false;
|
||
this._needAddFirstVertex = false;
|
||
this._lastFixedVertexPosition.setValue(0, 0, 0);
|
||
}
|
||
}
|
||
TrailGeometry.ALIGNMENT_VIEW = 0;
|
||
TrailGeometry.ALIGNMENT_TRANSFORM_Z = 1;
|
||
TrailGeometry._tempVector30 = new Vector3();
|
||
TrailGeometry._tempVector31 = new Vector3();
|
||
TrailGeometry._tempVector32 = new Vector3();
|
||
TrailGeometry._tempVector33 = new Vector3();
|
||
TrailGeometry._tempVector34 = new Vector3();
|
||
TrailGeometry._tempVector35 = new Vector3();
|
||
TrailGeometry._tempVector36 = new Vector3();
|
||
TrailGeometry._type = GeometryElement._typeCounter++;
|
||
|
||
class TrailFilter {
|
||
constructor(owner) {
|
||
this._totalLength = 0;
|
||
this._lastPosition = new Vector3();
|
||
this._curtime = 0;
|
||
this.alignment = TrailFilter.ALIGNMENT_VIEW;
|
||
this._owner = owner;
|
||
this._initDefaultData();
|
||
this.addRenderElement();
|
||
}
|
||
get time() {
|
||
return this._time;
|
||
}
|
||
set time(value) {
|
||
this._time = value;
|
||
this._owner._render._shaderValues.setNumber(TrailFilter.LIFETIME, value);
|
||
}
|
||
get minVertexDistance() {
|
||
return this._minVertexDistance;
|
||
}
|
||
set minVertexDistance(value) {
|
||
this._minVertexDistance = value;
|
||
}
|
||
get widthMultiplier() {
|
||
return this._widthMultiplier;
|
||
}
|
||
set widthMultiplier(value) {
|
||
this._widthMultiplier = value;
|
||
}
|
||
get widthCurve() {
|
||
return this._widthCurve;
|
||
}
|
||
set widthCurve(value) {
|
||
this._widthCurve = value;
|
||
var widthCurveFloatArray = new Float32Array(value.length * 4);
|
||
var i, j, index = 0;
|
||
for (i = 0, j = value.length; i < j; i++) {
|
||
widthCurveFloatArray[index++] = value[i].time;
|
||
widthCurveFloatArray[index++] = value[i].inTangent;
|
||
widthCurveFloatArray[index++] = value[i].outTangent;
|
||
widthCurveFloatArray[index++] = value[i].value;
|
||
}
|
||
this._owner._render._shaderValues.setBuffer(TrailFilter.WIDTHCURVE, widthCurveFloatArray);
|
||
this._owner._render._shaderValues.setInt(TrailFilter.WIDTHCURVEKEYLENGTH, value.length);
|
||
}
|
||
get colorGradient() {
|
||
return this._colorGradient;
|
||
}
|
||
set colorGradient(value) {
|
||
this._colorGradient = value;
|
||
}
|
||
get textureMode() {
|
||
return this._textureMode;
|
||
}
|
||
set textureMode(value) {
|
||
this._textureMode = value;
|
||
}
|
||
addRenderElement() {
|
||
var render = this._owner._render;
|
||
var elements = render._renderElements;
|
||
var material = render.sharedMaterials[0];
|
||
(material) || (material = TrailMaterial.defaultMaterial);
|
||
var element = new RenderElement();
|
||
element.setTransform(this._owner._transform);
|
||
element.render = render;
|
||
element.material = material;
|
||
this._trialGeometry = new TrailGeometry(this);
|
||
element.setGeometry(this._trialGeometry);
|
||
elements.push(element);
|
||
}
|
||
_update(state) {
|
||
var render = this._owner._render;
|
||
this._curtime += state.scene.timer._delta / 1000;
|
||
render._shaderValues.setNumber(TrailFilter.CURTIME, this._curtime);
|
||
var curPos = this._owner.transform.position;
|
||
var element = render._renderElements[0]._geometry;
|
||
element._updateDisappear();
|
||
element._updateTrail(state.camera, this._lastPosition, curPos);
|
||
element._updateVertexBufferUV();
|
||
curPos.cloneTo(this._lastPosition);
|
||
}
|
||
_initDefaultData() {
|
||
this.time = 5.0;
|
||
this.minVertexDistance = 0.1;
|
||
this.widthMultiplier = 1;
|
||
this.textureMode = TextureMode.Stretch;
|
||
var widthKeyFrames = [];
|
||
var widthKeyFrame1 = new FloatKeyframe();
|
||
widthKeyFrame1.time = 0;
|
||
widthKeyFrame1.inTangent = 0;
|
||
widthKeyFrame1.outTangent = 0;
|
||
widthKeyFrame1.value = 1;
|
||
widthKeyFrames.push(widthKeyFrame1);
|
||
var widthKeyFrame2 = new FloatKeyframe();
|
||
widthKeyFrame2.time = 1;
|
||
widthKeyFrame2.inTangent = 0;
|
||
widthKeyFrame2.outTangent = 0;
|
||
widthKeyFrame2.value = 1;
|
||
widthKeyFrames.push(widthKeyFrame2);
|
||
this.widthCurve = widthKeyFrames;
|
||
var gradient = new Gradient(2, 2);
|
||
gradient.mode = GradientMode.Blend;
|
||
gradient.addColorRGB(0, Color.WHITE);
|
||
gradient.addColorRGB(1, Color.WHITE);
|
||
gradient.addColorAlpha(0, 1);
|
||
gradient.addColorAlpha(1, 1);
|
||
this.colorGradient = gradient;
|
||
}
|
||
destroy() {
|
||
this._trialGeometry.destroy();
|
||
this._trialGeometry = null;
|
||
this._widthCurve = null;
|
||
this._colorGradient = null;
|
||
}
|
||
clear() {
|
||
this._trialGeometry.clear();
|
||
this._lastPosition.setValue(0, 0, 0);
|
||
this._curtime = 0;
|
||
this._totalLength = 0;
|
||
}
|
||
}
|
||
TrailFilter.CURTIME = Shader3D.propertyNameToID("u_CurTime");
|
||
TrailFilter.LIFETIME = Shader3D.propertyNameToID("u_LifeTime");
|
||
TrailFilter.WIDTHCURVE = Shader3D.propertyNameToID("u_WidthCurve");
|
||
TrailFilter.WIDTHCURVEKEYLENGTH = Shader3D.propertyNameToID("u_WidthCurveKeyLength");
|
||
TrailFilter.ALIGNMENT_VIEW = 0;
|
||
TrailFilter.ALIGNMENT_TRANSFORM_Z = 1;
|
||
|
||
class TrailRenderer extends BaseRender {
|
||
constructor(owner) {
|
||
super(owner);
|
||
this._projectionViewWorldMatrix = new Matrix4x4();
|
||
}
|
||
_calculateBoundingBox() {
|
||
}
|
||
_needRender(boundFrustum, context) {
|
||
this._owner.trailFilter._update(context);
|
||
if (boundFrustum)
|
||
return boundFrustum.intersects(this.bounds._getBoundBox());
|
||
else
|
||
return true;
|
||
}
|
||
_updateForNative(context) {
|
||
this._owner.trailFilter._update(context);
|
||
}
|
||
_renderUpdate(state, transform) {
|
||
super._renderUpdate(state, transform);
|
||
}
|
||
_renderUpdateWithCamera(context, transform) {
|
||
var projectionView = context.projectionViewMatrix;
|
||
if (transform) {
|
||
Matrix4x4.multiply(projectionView, transform.worldMatrix, this._projectionViewWorldMatrix);
|
||
this._shaderValues.setMatrix4x4(Sprite3D.MVPMATRIX, this._projectionViewWorldMatrix);
|
||
}
|
||
else {
|
||
this._shaderValues.setMatrix4x4(Sprite3D.MVPMATRIX, projectionView);
|
||
}
|
||
}
|
||
}
|
||
|
||
class TrailSprite3D extends RenderableSprite3D {
|
||
constructor(name = null) {
|
||
super(name);
|
||
this._render = new TrailRenderer(this);
|
||
this._geometryFilter = new TrailFilter(this);
|
||
}
|
||
static __init__() {
|
||
}
|
||
get trailFilter() {
|
||
return this._geometryFilter;
|
||
}
|
||
get trailRenderer() {
|
||
return this._render;
|
||
}
|
||
_parse(data, spriteMap) {
|
||
super._parse(data, spriteMap);
|
||
var render = this._render;
|
||
var filter = this._geometryFilter;
|
||
var i, j;
|
||
var materials = data.materials;
|
||
if (materials) {
|
||
var sharedMaterials = render.sharedMaterials;
|
||
var materialCount = materials.length;
|
||
sharedMaterials.length = materialCount;
|
||
for (i = 0; i < materialCount; i++)
|
||
sharedMaterials[i] = Laya.Loader.getRes(materials[i].path);
|
||
render.sharedMaterials = sharedMaterials;
|
||
}
|
||
filter.time = data.time;
|
||
filter.minVertexDistance = data.minVertexDistance;
|
||
filter.widthMultiplier = data.widthMultiplier;
|
||
filter.textureMode = data.textureMode;
|
||
(data.alignment != null) && (filter.alignment = data.alignment);
|
||
var widthCurve = [];
|
||
var widthCurveData = data.widthCurve;
|
||
for (i = 0, j = widthCurveData.length; i < j; i++) {
|
||
var trailkeyframe = new FloatKeyframe();
|
||
trailkeyframe.time = widthCurveData[i].time;
|
||
trailkeyframe.inTangent = widthCurveData[i].inTangent;
|
||
trailkeyframe.outTangent = widthCurveData[i].outTangent;
|
||
trailkeyframe.value = widthCurveData[i].value;
|
||
widthCurve.push(trailkeyframe);
|
||
}
|
||
filter.widthCurve = widthCurve;
|
||
var colorGradientData = data.colorGradient;
|
||
var colorKeys = colorGradientData.colorKeys;
|
||
var alphaKeys = colorGradientData.alphaKeys;
|
||
var colorGradient = new Gradient(colorKeys.length, alphaKeys.length);
|
||
colorGradient.mode = colorGradientData.mode;
|
||
for (i = 0, j = colorKeys.length; i < j; i++) {
|
||
var colorKey = colorKeys[i];
|
||
colorGradient.addColorRGB(colorKey.time, new Color(colorKey.value[0], colorKey.value[1], colorKey.value[2], 1.0));
|
||
}
|
||
for (i = 0, j = alphaKeys.length; i < j; i++) {
|
||
var alphaKey = alphaKeys[i];
|
||
colorGradient.addColorAlpha(alphaKey.time, alphaKey.value);
|
||
}
|
||
filter.colorGradient = colorGradient;
|
||
}
|
||
_onActive() {
|
||
super._onActive();
|
||
this._transform.position.cloneTo(this._geometryFilter._lastPosition);
|
||
}
|
||
_cloneTo(destObject, srcSprite, dstSprite) {
|
||
super._cloneTo(destObject, srcSprite, dstSprite);
|
||
var i, j;
|
||
var destTrailSprite3D = destObject;
|
||
var destTrailFilter = destTrailSprite3D.trailFilter;
|
||
destTrailFilter.time = this.trailFilter.time;
|
||
destTrailFilter.minVertexDistance = this.trailFilter.minVertexDistance;
|
||
destTrailFilter.widthMultiplier = this.trailFilter.widthMultiplier;
|
||
destTrailFilter.textureMode = this.trailFilter.textureMode;
|
||
destTrailFilter.alignment = this.trailFilter.alignment;
|
||
var widthCurveData = this.trailFilter.widthCurve;
|
||
var widthCurve = [];
|
||
for (i = 0, j = widthCurveData.length; i < j; i++) {
|
||
var keyFrame = new FloatKeyframe();
|
||
widthCurveData[i].cloneTo(keyFrame);
|
||
widthCurve.push(keyFrame);
|
||
}
|
||
destTrailFilter.widthCurve = widthCurve;
|
||
var destColorGradient = new Gradient(this.trailFilter.colorGradient.maxColorRGBKeysCount, this.trailFilter.colorGradient.maxColorAlphaKeysCount);
|
||
this.trailFilter.colorGradient.cloneTo(destColorGradient);
|
||
destTrailFilter.colorGradient = destColorGradient;
|
||
var destTrailRender = destTrailSprite3D.trailRenderer;
|
||
destTrailRender.sharedMaterial = this.trailRenderer.sharedMaterial;
|
||
}
|
||
destroy(destroyChild = true) {
|
||
if (this.destroyed)
|
||
return;
|
||
super.destroy(destroyChild);
|
||
this._geometryFilter.destroy();
|
||
this._geometryFilter = null;
|
||
}
|
||
clear() {
|
||
this._geometryFilter.clear();
|
||
}
|
||
_create() {
|
||
return new TrailSprite3D();
|
||
}
|
||
}
|
||
|
||
class VertexPositionTerrain {
|
||
constructor(position, normal, textureCoord0, textureCoord1) {
|
||
this._position = position;
|
||
this._normal = normal;
|
||
this._textureCoord0 = textureCoord0;
|
||
this._textureCoord1 = textureCoord1;
|
||
}
|
||
static __init__() {
|
||
VertexPositionTerrain._vertexDeclaration = new VertexDeclaration(40, [new VertexElement(0, VertexElementFormat.Vector3, VertexPositionTerrain.TERRAIN_POSITION0),
|
||
new VertexElement(12, VertexElementFormat.Vector3, VertexPositionTerrain.TERRAIN_NORMAL0),
|
||
new VertexElement(24, VertexElementFormat.Vector2, VertexPositionTerrain.TERRAIN_TEXTURECOORDINATE0),
|
||
new VertexElement(32, VertexElementFormat.Vector2, VertexPositionTerrain.TERRAIN_TEXTURECOORDINATE1)]);
|
||
}
|
||
static get vertexDeclaration() {
|
||
return VertexPositionTerrain._vertexDeclaration;
|
||
}
|
||
get position() {
|
||
return this._position;
|
||
}
|
||
get normal() {
|
||
return this._normal;
|
||
}
|
||
get textureCoord0() {
|
||
return this._textureCoord0;
|
||
}
|
||
get textureCoord1() {
|
||
return this._textureCoord1;
|
||
}
|
||
get vertexDeclaration() {
|
||
return VertexPositionTerrain._vertexDeclaration;
|
||
}
|
||
}
|
||
VertexPositionTerrain.TERRAIN_POSITION0 = 0;
|
||
VertexPositionTerrain.TERRAIN_NORMAL0 = 1;
|
||
VertexPositionTerrain.TERRAIN_TEXTURECOORDINATE0 = 2;
|
||
VertexPositionTerrain.TERRAIN_TEXTURECOORDINATE1 = 3;
|
||
|
||
class SubMesh extends GeometryElement {
|
||
constructor(mesh) {
|
||
super();
|
||
this._id = ++SubMesh._uniqueIDCounter;
|
||
this._mesh = mesh;
|
||
this._boneIndicesList = [];
|
||
this._subIndexBufferStart = [];
|
||
this._subIndexBufferCount = [];
|
||
}
|
||
get indexCount() {
|
||
return this._indexCount;
|
||
}
|
||
_setIndexRange(indexStart, indexCount, indexFormat = exports.IndexFormat.UInt16) {
|
||
this._indexStart = indexStart;
|
||
this._indexCount = indexCount;
|
||
if (indexFormat == exports.IndexFormat.UInt16) {
|
||
this._indices = new Uint16Array(this._indexBuffer.getData().buffer, indexStart * 2, indexCount);
|
||
}
|
||
else {
|
||
this._indices = new Uint32Array(this._indexBuffer.getData().buffer, indexStart * 4, indexCount);
|
||
}
|
||
}
|
||
_getType() {
|
||
return SubMesh._type;
|
||
}
|
||
_prepareRender(state) {
|
||
this._mesh._uploadVerticesData();
|
||
return true;
|
||
}
|
||
_render(state) {
|
||
var mesh = this._mesh;
|
||
if (mesh.indexFormat === exports.IndexFormat.UInt32 && !Laya.LayaGL.layaGPUInstance.supportElementIndexUint32()) {
|
||
console.warn("SubMesh:this device do not support IndexFormat.UInt32.");
|
||
return;
|
||
}
|
||
var gl = Laya.LayaGL.instance;
|
||
var skinnedDatas = state.renderElement ? state.renderElement.render._skinnedData : null;
|
||
var glIndexFormat;
|
||
var byteCount;
|
||
switch (mesh.indexFormat) {
|
||
case exports.IndexFormat.UInt32:
|
||
glIndexFormat = gl.UNSIGNED_INT;
|
||
byteCount = 4;
|
||
break;
|
||
case exports.IndexFormat.UInt16:
|
||
glIndexFormat = gl.UNSIGNED_SHORT;
|
||
byteCount = 2;
|
||
break;
|
||
case exports.IndexFormat.UInt8:
|
||
glIndexFormat = gl.UNSIGNED_BYTE;
|
||
byteCount = 1;
|
||
break;
|
||
}
|
||
mesh._bufferState.bind();
|
||
if (skinnedDatas) {
|
||
var subSkinnedDatas = skinnedDatas[this._indexInMesh];
|
||
for (var i = 0, n = this._boneIndicesList.length; i < n; i++) {
|
||
state.shader.uploadCustomUniform(SkinnedMeshSprite3D.BONES, subSkinnedDatas[i]);
|
||
gl.drawElements(gl.TRIANGLES, this._subIndexBufferCount[i], glIndexFormat, this._subIndexBufferStart[i] * byteCount);
|
||
}
|
||
}
|
||
else {
|
||
gl.drawElements(gl.TRIANGLES, this._indexCount, glIndexFormat, this._indexStart * byteCount);
|
||
}
|
||
Laya.Stat.trianglesFaces += this._indexCount / 3;
|
||
Laya.Stat.renderBatches++;
|
||
}
|
||
getIndices() {
|
||
if (this._mesh._isReadable)
|
||
return this._indices.slice();
|
||
else
|
||
throw "SubMesh:can't get indices on subMesh,mesh's isReadable must be true.";
|
||
}
|
||
setIndices(indices) {
|
||
this._indexBuffer.setData(indices, this._indexStart, 0, this._indexCount);
|
||
}
|
||
destroy() {
|
||
if (this._destroyed)
|
||
return;
|
||
super.destroy();
|
||
this._indexBuffer.destroy();
|
||
this._indexBuffer = null;
|
||
this._mesh = null;
|
||
this._boneIndicesList = null;
|
||
this._subIndexBufferStart = null;
|
||
this._subIndexBufferCount = null;
|
||
this._skinAnimationDatas = null;
|
||
}
|
||
}
|
||
SubMesh._uniqueIDCounter = 0;
|
||
SubMesh._type = GeometryElement._typeCounter++;
|
||
|
||
class skinnedMatrixCache {
|
||
constructor(subMeshIndex, batchIndex, batchBoneIndex) {
|
||
this.subMeshIndex = subMeshIndex;
|
||
this.batchIndex = batchIndex;
|
||
this.batchBoneIndex = batchBoneIndex;
|
||
}
|
||
}
|
||
class Mesh extends Laya.Resource {
|
||
constructor(isReadable = true) {
|
||
super();
|
||
this._tempVector30 = new Vector3();
|
||
this._tempVector31 = new Vector3();
|
||
this._tempVector32 = new Vector3();
|
||
this._minVerticesUpdate = -1;
|
||
this._maxVerticesUpdate = -1;
|
||
this._needUpdateBounds = true;
|
||
this._bounds = new Bounds(new Vector3(), new Vector3());
|
||
this._bufferState = new BufferState();
|
||
this._instanceBufferState = new BufferState();
|
||
this._instanceBufferStateType = 0;
|
||
this._vertexBuffer = null;
|
||
this._indexBuffer = null;
|
||
this._skinnedMatrixCaches = [];
|
||
this._vertexCount = 0;
|
||
this._indexFormat = exports.IndexFormat.UInt16;
|
||
this._isReadable = isReadable;
|
||
this._subMeshes = [];
|
||
}
|
||
static __init__() {
|
||
var physics3D = Physics3D._bullet;
|
||
if (physics3D) {
|
||
Mesh._nativeTempVector30 = physics3D.btVector3_create(0, 0, 0);
|
||
Mesh._nativeTempVector31 = physics3D.btVector3_create(0, 0, 0);
|
||
Mesh._nativeTempVector32 = physics3D.btVector3_create(0, 0, 0);
|
||
}
|
||
}
|
||
static load(url, complete) {
|
||
Laya.ILaya.loader.create(url, complete, null, Mesh.MESH);
|
||
}
|
||
get inverseAbsoluteBindPoses() {
|
||
return this._inverseBindPoses;
|
||
}
|
||
get vertexCount() {
|
||
return this._vertexCount;
|
||
}
|
||
get indexCount() {
|
||
return this._indexBuffer.indexCount;
|
||
}
|
||
get subMeshCount() {
|
||
return this._subMeshes.length;
|
||
}
|
||
get bounds() {
|
||
return this._bounds;
|
||
}
|
||
set bounds(value) {
|
||
if (this._bounds !== value)
|
||
value.cloneTo(this._bounds);
|
||
}
|
||
get indexFormat() {
|
||
return this._indexFormat;
|
||
}
|
||
_getPositionElement(vertexBuffer) {
|
||
var vertexElements = vertexBuffer.vertexDeclaration._vertexElements;
|
||
for (var i = 0, n = vertexElements.length; i < n; i++) {
|
||
var vertexElement = vertexElements[i];
|
||
if (vertexElement._elementFormat === VertexElementFormat.Vector3 && vertexElement._elementUsage === VertexMesh.MESH_POSITION0)
|
||
return vertexElement;
|
||
}
|
||
return null;
|
||
}
|
||
_getVerticeElementData(data, elementUsage) {
|
||
data.length = this._vertexCount;
|
||
var verDec = this._vertexBuffer.vertexDeclaration;
|
||
var element = verDec.getVertexElementByUsage(elementUsage);
|
||
if (element) {
|
||
var uint8Vertices = this._vertexBuffer.getUint8Data();
|
||
var floatVertices = this._vertexBuffer.getFloat32Data();
|
||
var uint8VerStr = verDec.vertexStride;
|
||
var floatVerStr = uint8VerStr / 4;
|
||
var uint8EleOffset = element._offset;
|
||
var floatEleOffset = uint8EleOffset / 4;
|
||
switch (elementUsage) {
|
||
case VertexMesh.MESH_TEXTURECOORDINATE0:
|
||
case VertexMesh.MESH_TEXTURECOORDINATE1:
|
||
for (var i = 0; i < this._vertexCount; i++) {
|
||
var offset = floatVerStr * i + floatEleOffset;
|
||
data[i] = new Vector2(floatVertices[offset], floatVertices[offset + 1]);
|
||
}
|
||
break;
|
||
case VertexMesh.MESH_POSITION0:
|
||
case VertexMesh.MESH_NORMAL0:
|
||
for (var i = 0; i < this._vertexCount; i++) {
|
||
var offset = floatVerStr * i + floatEleOffset;
|
||
data[i] = new Vector3(floatVertices[offset], floatVertices[offset + 1], floatVertices[offset + 2]);
|
||
}
|
||
break;
|
||
case VertexMesh.MESH_TANGENT0:
|
||
case VertexMesh.MESH_BLENDWEIGHT0:
|
||
for (var i = 0; i < this._vertexCount; i++) {
|
||
var offset = floatVerStr * i + floatEleOffset;
|
||
data[i] = new Vector4(floatVertices[offset], floatVertices[offset + 1], floatVertices[offset + 2], floatVertices[offset + 3]);
|
||
}
|
||
break;
|
||
case VertexMesh.MESH_COLOR0:
|
||
for (var i = 0; i < this._vertexCount; i++) {
|
||
var offset = floatVerStr * i + floatEleOffset;
|
||
data[i] = new Color(floatVertices[offset], floatVertices[offset + 1], floatVertices[offset + 2], floatVertices[offset + 3]);
|
||
}
|
||
break;
|
||
case VertexMesh.MESH_BLENDINDICES0:
|
||
for (var i = 0; i < this._vertexCount; i++) {
|
||
var offset = uint8VerStr * i + uint8EleOffset;
|
||
data[i] = new Vector4(uint8Vertices[offset], uint8Vertices[offset + 1], uint8Vertices[offset + 2], uint8Vertices[offset + 3]);
|
||
}
|
||
break;
|
||
default:
|
||
throw "Mesh:Unknown elementUsage.";
|
||
}
|
||
}
|
||
}
|
||
_setVerticeElementData(data, elementUsage) {
|
||
var verDec = this._vertexBuffer.vertexDeclaration;
|
||
var element = verDec.getVertexElementByUsage(elementUsage);
|
||
if (element) {
|
||
var uint8Vertices = this._vertexBuffer.getUint8Data();
|
||
var floatVertices = this._vertexBuffer.getFloat32Data();
|
||
var uint8VerStr = verDec.vertexStride;
|
||
var float8VerStr = uint8VerStr / 4;
|
||
var uint8EleOffset = element._offset;
|
||
var floatEleOffset = uint8EleOffset / 4;
|
||
switch (elementUsage) {
|
||
case VertexMesh.MESH_TEXTURECOORDINATE0:
|
||
case VertexMesh.MESH_TEXTURECOORDINATE1:
|
||
for (var i = 0, n = data.length; i < n; i++) {
|
||
var offset = float8VerStr * i + floatEleOffset;
|
||
var vec2 = data[i];
|
||
floatVertices[offset] = vec2.x;
|
||
floatVertices[offset + 1] = vec2.y;
|
||
}
|
||
break;
|
||
case VertexMesh.MESH_POSITION0:
|
||
case VertexMesh.MESH_NORMAL0:
|
||
for (var i = 0, n = data.length; i < n; i++) {
|
||
var offset = float8VerStr * i + floatEleOffset;
|
||
var vec3 = data[i];
|
||
floatVertices[offset] = vec3.x;
|
||
floatVertices[offset + 1] = vec3.y;
|
||
floatVertices[offset + 2] = vec3.z;
|
||
}
|
||
break;
|
||
case VertexMesh.MESH_TANGENT0:
|
||
case VertexMesh.MESH_BLENDWEIGHT0:
|
||
for (var i = 0, n = data.length; i < n; i++) {
|
||
var offset = float8VerStr * i + floatEleOffset;
|
||
var vec4 = data[i];
|
||
floatVertices[offset] = vec4.x;
|
||
floatVertices[offset + 1] = vec4.y;
|
||
floatVertices[offset + 2] = vec4.z;
|
||
floatVertices[offset + 3] = vec4.w;
|
||
}
|
||
break;
|
||
case VertexMesh.MESH_COLOR0:
|
||
for (var i = 0, n = data.length; i < n; i++) {
|
||
var offset = float8VerStr * i + floatEleOffset;
|
||
var cor = data[i];
|
||
floatVertices[offset] = cor.r;
|
||
floatVertices[offset + 1] = cor.g;
|
||
floatVertices[offset + 2] = cor.b;
|
||
floatVertices[offset + 3] = cor.a;
|
||
}
|
||
break;
|
||
case VertexMesh.MESH_BLENDINDICES0:
|
||
for (var i = 0, n = data.length; i < n; i++) {
|
||
var offset = uint8VerStr * i + uint8EleOffset;
|
||
var vec4 = data[i];
|
||
uint8Vertices[offset] = vec4.x;
|
||
uint8Vertices[offset + 1] = vec4.y;
|
||
uint8Vertices[offset + 2] = vec4.z;
|
||
uint8Vertices[offset + 3] = vec4.w;
|
||
}
|
||
break;
|
||
default:
|
||
throw "Mesh:Unknown elementUsage.";
|
||
}
|
||
this._minVerticesUpdate = 0;
|
||
this._maxVerticesUpdate = Number.MAX_SAFE_INTEGER;
|
||
}
|
||
else {
|
||
console.warn("Mesh: the mesh don't have this VertexElement.");
|
||
}
|
||
}
|
||
_disposeResource() {
|
||
for (var i = 0, n = this._subMeshes.length; i < n; i++)
|
||
this._subMeshes[i].destroy();
|
||
this._btTriangleMesh && Physics3D._bullet.btStridingMeshInterface_destroy(this._btTriangleMesh);
|
||
this._vertexBuffer.destroy();
|
||
this._indexBuffer.destroy();
|
||
this._bufferState.destroy();
|
||
this._instanceBufferState.destroy();
|
||
this._setCPUMemory(0);
|
||
this._setGPUMemory(0);
|
||
this._bufferState = null;
|
||
this._instanceBufferState = null;
|
||
this._vertexBuffer = null;
|
||
this._indexBuffer = null;
|
||
this._subMeshes = null;
|
||
this._btTriangleMesh = null;
|
||
this._indexBuffer = null;
|
||
this._boneNames = null;
|
||
this._inverseBindPoses = null;
|
||
}
|
||
_setSubMeshes(subMeshes) {
|
||
this._subMeshes = subMeshes;
|
||
for (var i = 0, n = subMeshes.length; i < n; i++)
|
||
subMeshes[i]._indexInMesh = i;
|
||
}
|
||
_setBuffer(vertexBuffer, indexBuffer) {
|
||
var bufferState = this._bufferState;
|
||
bufferState.bind();
|
||
bufferState.applyVertexBuffer(vertexBuffer);
|
||
bufferState.applyIndexBuffer(indexBuffer);
|
||
bufferState.unBind();
|
||
}
|
||
_setInstanceBuffer(instanceBufferStateType) {
|
||
var instanceBufferState = this._instanceBufferState;
|
||
instanceBufferState.bind();
|
||
instanceBufferState.applyVertexBuffer(this._vertexBuffer);
|
||
instanceBufferState.applyInstanceVertexBuffer(SubMeshInstanceBatch.instance.instanceWorldMatrixBuffer);
|
||
switch (instanceBufferStateType) {
|
||
case Mesh.MESH_INSTANCEBUFFER_TYPE_SIMPLEANIMATOR:
|
||
instanceBufferState.applyInstanceVertexBuffer(SubMeshInstanceBatch.instance.instanceSimpleAnimatorBuffer);
|
||
break;
|
||
}
|
||
instanceBufferState.applyIndexBuffer(this._indexBuffer);
|
||
instanceBufferState.unBind();
|
||
}
|
||
_getPhysicMesh() {
|
||
if (!this._btTriangleMesh) {
|
||
var bt = Physics3D._bullet;
|
||
var triangleMesh = bt.btTriangleMesh_create();
|
||
var nativePositio0 = Mesh._nativeTempVector30;
|
||
var nativePositio1 = Mesh._nativeTempVector31;
|
||
var nativePositio2 = Mesh._nativeTempVector32;
|
||
var position0 = this._tempVector30;
|
||
var position1 = this._tempVector31;
|
||
var position2 = this._tempVector32;
|
||
var vertexBuffer = this._vertexBuffer;
|
||
var positionElement = this._getPositionElement(vertexBuffer);
|
||
var verticesData = vertexBuffer.getFloat32Data();
|
||
var floatCount = vertexBuffer.vertexDeclaration.vertexStride / 4;
|
||
var posOffset = positionElement._offset / 4;
|
||
var indices = this._indexBuffer.getData();
|
||
for (var i = 0, n = indices.length; i < n; i += 3) {
|
||
var p0Index = indices[i] * floatCount + posOffset;
|
||
var p1Index = indices[i + 1] * floatCount + posOffset;
|
||
var p2Index = indices[i + 2] * floatCount + posOffset;
|
||
position0.setValue(verticesData[p0Index], verticesData[p0Index + 1], verticesData[p0Index + 2]);
|
||
position1.setValue(verticesData[p1Index], verticesData[p1Index + 1], verticesData[p1Index + 2]);
|
||
position2.setValue(verticesData[p2Index], verticesData[p2Index + 1], verticesData[p2Index + 2]);
|
||
Utils3D._convertToBulletVec3(position0, nativePositio0, true);
|
||
Utils3D._convertToBulletVec3(position1, nativePositio1, true);
|
||
Utils3D._convertToBulletVec3(position2, nativePositio2, true);
|
||
bt.btTriangleMesh_addTriangle(triangleMesh, nativePositio0, nativePositio1, nativePositio2, true);
|
||
}
|
||
this._btTriangleMesh = triangleMesh;
|
||
}
|
||
return this._btTriangleMesh;
|
||
}
|
||
_uploadVerticesData() {
|
||
var min = this._minVerticesUpdate;
|
||
var max = this._maxVerticesUpdate;
|
||
if (min !== -1 && max !== -1) {
|
||
var offset = min;
|
||
this._vertexBuffer.setData(this._vertexBuffer.getUint8Data().buffer, offset, offset, max - min);
|
||
this._minVerticesUpdate = -1;
|
||
this._maxVerticesUpdate = -1;
|
||
}
|
||
}
|
||
getSubMesh(index) {
|
||
return this._subMeshes[index];
|
||
}
|
||
getPositions(positions) {
|
||
if (this._isReadable)
|
||
this._getVerticeElementData(positions, VertexMesh.MESH_POSITION0);
|
||
else
|
||
throw "Mesh:can't get positions on mesh,isReadable must be true.";
|
||
}
|
||
setPositions(positions) {
|
||
if (this._isReadable) {
|
||
this._setVerticeElementData(positions, VertexMesh.MESH_POSITION0);
|
||
this._needUpdateBounds = true;
|
||
}
|
||
else {
|
||
throw "Mesh:setPosition() need isReadable must be true or use setVertices().";
|
||
}
|
||
}
|
||
getColors(colors) {
|
||
if (this._isReadable)
|
||
this._getVerticeElementData(colors, VertexMesh.MESH_COLOR0);
|
||
else
|
||
throw "Mesh:can't get colors on mesh,isReadable must be true.";
|
||
}
|
||
setColors(colors) {
|
||
if (this._isReadable)
|
||
this._setVerticeElementData(colors, VertexMesh.MESH_COLOR0);
|
||
else
|
||
throw "Mesh:setColors() need isReadable must be true or use setVertices().";
|
||
}
|
||
getUVs(uvs, channel = 0) {
|
||
if (this._isReadable) {
|
||
switch (channel) {
|
||
case 0:
|
||
this._getVerticeElementData(uvs, VertexMesh.MESH_TEXTURECOORDINATE0);
|
||
break;
|
||
case 1:
|
||
this._getVerticeElementData(uvs, VertexMesh.MESH_TEXTURECOORDINATE1);
|
||
break;
|
||
default:
|
||
throw "Mesh:Invalid channel.";
|
||
}
|
||
}
|
||
else {
|
||
throw "Mesh:can't get uvs on mesh,isReadable must be true.";
|
||
}
|
||
}
|
||
setUVs(uvs, channel = 0) {
|
||
if (this._isReadable) {
|
||
switch (channel) {
|
||
case 0:
|
||
this._setVerticeElementData(uvs, VertexMesh.MESH_TEXTURECOORDINATE0);
|
||
break;
|
||
case 1:
|
||
this._setVerticeElementData(uvs, VertexMesh.MESH_TEXTURECOORDINATE1);
|
||
break;
|
||
default:
|
||
throw "Mesh:Invalid channel.";
|
||
}
|
||
}
|
||
else {
|
||
throw "Mesh:setUVs() need isReadable must be true or use setVertices().";
|
||
}
|
||
}
|
||
getNormals(normals) {
|
||
if (this._isReadable)
|
||
this._getVerticeElementData(normals, VertexMesh.MESH_NORMAL0);
|
||
else
|
||
throw "Mesh:can't get colors on mesh,isReadable must be true.";
|
||
}
|
||
setNormals(normals) {
|
||
if (this._isReadable)
|
||
this._setVerticeElementData(normals, VertexMesh.MESH_NORMAL0);
|
||
else
|
||
throw "Mesh:setNormals() need must be true or use setVertices().";
|
||
}
|
||
getTangents(tangents) {
|
||
if (this._isReadable)
|
||
this._getVerticeElementData(tangents, VertexMesh.MESH_TANGENT0);
|
||
else
|
||
throw "Mesh:can't get colors on mesh,isReadable must be true.";
|
||
}
|
||
setTangents(tangents) {
|
||
if (this._isReadable)
|
||
this._setVerticeElementData(tangents, VertexMesh.MESH_TANGENT0);
|
||
else
|
||
throw "Mesh:setTangents() need isReadable must be true or use setVertices().";
|
||
}
|
||
getBoneWeights(boneWeights) {
|
||
if (this._isReadable)
|
||
this._getVerticeElementData(boneWeights, VertexMesh.MESH_BLENDWEIGHT0);
|
||
else
|
||
throw "Mesh:can't get boneWeights on mesh,isReadable must be true.";
|
||
}
|
||
setBoneWeights(boneWeights) {
|
||
if (this._isReadable)
|
||
this._setVerticeElementData(boneWeights, VertexMesh.MESH_BLENDWEIGHT0);
|
||
else
|
||
throw "Mesh:setBoneWeights() need isReadable must be true or use setVertices().";
|
||
}
|
||
getBoneIndices(boneIndices) {
|
||
if (this._isReadable)
|
||
this._getVerticeElementData(boneIndices, VertexMesh.MESH_BLENDINDICES0);
|
||
else
|
||
throw "Mesh:can't get boneIndices on mesh,isReadable must be true.";
|
||
}
|
||
setBoneIndices(boneIndices) {
|
||
if (this._isReadable)
|
||
this._setVerticeElementData(boneIndices, VertexMesh.MESH_BLENDINDICES0);
|
||
else
|
||
throw "Mesh:setBoneIndices() need isReadable must be true or use setVertices().";
|
||
}
|
||
markAsUnreadbale() {
|
||
this._uploadVerticesData();
|
||
this._vertexBuffer.markAsUnreadbale();
|
||
this._isReadable = false;
|
||
}
|
||
getVertexDeclaration() {
|
||
return this._vertexBuffer._vertexDeclaration;
|
||
}
|
||
getVertices() {
|
||
if (this._isReadable)
|
||
return this._vertexBuffer.getUint8Data().buffer.slice(0);
|
||
else
|
||
throw "Mesh:can't get vertices on mesh,isReadable must be true.";
|
||
}
|
||
setVertices(vertices) {
|
||
this._vertexBuffer.setData(vertices);
|
||
this._needUpdateBounds = true;
|
||
}
|
||
getIndices() {
|
||
if (this._isReadable)
|
||
return this._indexBuffer.getData().slice();
|
||
else
|
||
throw "Mesh:can't get indices on subMesh,mesh's isReadable must be true.";
|
||
}
|
||
setIndices(indices) {
|
||
var format;
|
||
if (indices instanceof Uint32Array)
|
||
format = exports.IndexFormat.UInt32;
|
||
else if (indices instanceof Uint16Array)
|
||
format = exports.IndexFormat.UInt16;
|
||
else if (indices instanceof Uint8Array)
|
||
format = exports.IndexFormat.UInt8;
|
||
var indexBuffer = this._indexBuffer;
|
||
if (this._indexFormat !== format || indexBuffer.indexCount !== indices.length) {
|
||
indexBuffer.destroy();
|
||
this._indexBuffer = indexBuffer = new IndexBuffer3D(format, indices.length, Laya.LayaGL.instance.STATIC_DRAW, this._isReadable);
|
||
}
|
||
indexBuffer.setData(indices);
|
||
this._indexFormat = format;
|
||
}
|
||
calculateBounds() {
|
||
if (this._isReadable) {
|
||
if (this._needUpdateBounds) {
|
||
var min = this._tempVector30;
|
||
var max = this._tempVector31;
|
||
min.x = min.y = min.z = Number.MAX_VALUE;
|
||
max.x = max.y = max.z = -Number.MAX_VALUE;
|
||
var vertexBuffer = this._vertexBuffer;
|
||
var positionElement = this._getPositionElement(vertexBuffer);
|
||
var verticesData = vertexBuffer.getFloat32Data();
|
||
var floatCount = vertexBuffer.vertexDeclaration.vertexStride / 4;
|
||
var posOffset = positionElement._offset / 4;
|
||
for (var j = 0, m = verticesData.length; j < m; j += floatCount) {
|
||
var ofset = j + posOffset;
|
||
var pX = verticesData[ofset];
|
||
var pY = verticesData[ofset + 1];
|
||
var pZ = verticesData[ofset + 2];
|
||
min.x = Math.min(min.x, pX);
|
||
min.y = Math.min(min.y, pY);
|
||
min.z = Math.min(min.z, pZ);
|
||
max.x = Math.max(max.x, pX);
|
||
max.y = Math.max(max.y, pY);
|
||
max.z = Math.max(max.z, pZ);
|
||
}
|
||
this._bounds.setMin(min);
|
||
this._bounds.setMax(max);
|
||
this._needUpdateBounds = false;
|
||
}
|
||
}
|
||
else {
|
||
throw "Mesh:can't calculate bounds on subMesh,mesh's isReadable must be true.";
|
||
}
|
||
}
|
||
cloneTo(destObject) {
|
||
var destMesh = destObject;
|
||
var vb = this._vertexBuffer;
|
||
var destVB = new VertexBuffer3D(vb._byteLength, vb.bufferUsage, vb.canRead);
|
||
destVB.vertexDeclaration = vb.vertexDeclaration;
|
||
destVB.setData(vb.getUint8Data().slice().buffer);
|
||
destMesh._vertexBuffer = destVB;
|
||
destMesh._vertexCount = this._vertexCount;
|
||
var ib = this._indexBuffer;
|
||
var destIB = new IndexBuffer3D(exports.IndexFormat.UInt16, ib.indexCount, ib.bufferUsage, ib.canRead);
|
||
destIB.setData(ib.getData().slice());
|
||
destMesh._indexBuffer = destIB;
|
||
destMesh._setBuffer(destMesh._vertexBuffer, destIB);
|
||
destMesh._setInstanceBuffer(this._instanceBufferStateType);
|
||
destMesh._setCPUMemory(this.cpuMemory);
|
||
destMesh._setGPUMemory(this.gpuMemory);
|
||
var i;
|
||
var boneNames = this._boneNames;
|
||
if (boneNames) {
|
||
var destBoneNames = destMesh._boneNames = [];
|
||
for (i = 0; i < boneNames.length; i++)
|
||
destBoneNames[i] = boneNames[i];
|
||
}
|
||
var inverseBindPoses = this._inverseBindPoses;
|
||
if (inverseBindPoses) {
|
||
var destInverseBindPoses = destMesh._inverseBindPoses = [];
|
||
for (i = 0; i < inverseBindPoses.length; i++)
|
||
destInverseBindPoses[i] = inverseBindPoses[i];
|
||
}
|
||
var cacheLength = this._skinnedMatrixCaches.length;
|
||
destMesh._skinnedMatrixCaches.length = cacheLength;
|
||
for (i = 0; i < cacheLength; i++) {
|
||
var skinnedCache = this._skinnedMatrixCaches[i];
|
||
destMesh._skinnedMatrixCaches[i] = new skinnedMatrixCache(skinnedCache.subMeshIndex, skinnedCache.batchIndex, skinnedCache.batchBoneIndex);
|
||
}
|
||
for (i = 0; i < this.subMeshCount; i++) {
|
||
var subMesh = this._subMeshes[i];
|
||
var subIndexBufferStart = subMesh._subIndexBufferStart;
|
||
var subIndexBufferCount = subMesh._subIndexBufferCount;
|
||
var boneIndicesList = subMesh._boneIndicesList;
|
||
var destSubmesh = new SubMesh(destMesh);
|
||
destSubmesh._subIndexBufferStart.length = subIndexBufferStart.length;
|
||
destSubmesh._subIndexBufferCount.length = subIndexBufferCount.length;
|
||
destSubmesh._boneIndicesList.length = boneIndicesList.length;
|
||
for (var j = 0; j < subIndexBufferStart.length; j++)
|
||
destSubmesh._subIndexBufferStart[j] = subIndexBufferStart[j];
|
||
for (j = 0; j < subIndexBufferCount.length; j++)
|
||
destSubmesh._subIndexBufferCount[j] = subIndexBufferCount[j];
|
||
for (j = 0; j < boneIndicesList.length; j++)
|
||
destSubmesh._boneIndicesList[j] = new Uint16Array(boneIndicesList[j]);
|
||
destSubmesh._indexBuffer = destIB;
|
||
destSubmesh._indexStart = subMesh._indexStart;
|
||
destSubmesh._indexCount = subMesh._indexCount;
|
||
destSubmesh._indices = new Uint16Array(destIB.getData().buffer, subMesh._indexStart * 2, subMesh._indexCount);
|
||
var vertexBuffer = destMesh._vertexBuffer;
|
||
destSubmesh._vertexBuffer = vertexBuffer;
|
||
destMesh._subMeshes.push(destSubmesh);
|
||
}
|
||
destMesh._setSubMeshes(destMesh._subMeshes);
|
||
}
|
||
clone() {
|
||
var dest = new Mesh();
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
}
|
||
Mesh.MESH = "MESH";
|
||
Mesh.MESH_INSTANCEBUFFER_TYPE_NORMAL = 0;
|
||
Mesh.MESH_INSTANCEBUFFER_TYPE_SIMPLEANIMATOR = 1;
|
||
|
||
class PrimitiveMesh {
|
||
static __init__() {
|
||
}
|
||
static _createMesh(vertexDeclaration, vertices, indices) {
|
||
var gl = Laya.LayaGL.instance;
|
||
var mesh = new Mesh();
|
||
var subMesh = new SubMesh(mesh);
|
||
var vertexBuffer = new VertexBuffer3D(vertices.length * 4, gl.STATIC_DRAW, true);
|
||
vertexBuffer.vertexDeclaration = vertexDeclaration;
|
||
vertexBuffer.setData(vertices.buffer);
|
||
mesh._vertexBuffer = vertexBuffer;
|
||
mesh._vertexCount = vertexBuffer._byteLength / vertexDeclaration.vertexStride;
|
||
var indexBuffer = new IndexBuffer3D(exports.IndexFormat.UInt16, indices.length, gl.STATIC_DRAW, true);
|
||
indexBuffer.setData(indices);
|
||
mesh._indexBuffer = indexBuffer;
|
||
mesh._setBuffer(vertexBuffer, indexBuffer);
|
||
mesh._setInstanceBuffer(mesh._instanceBufferStateType);
|
||
subMesh._vertexBuffer = vertexBuffer;
|
||
subMesh._indexBuffer = indexBuffer;
|
||
subMesh._setIndexRange(0, indexBuffer.indexCount);
|
||
var subIndexBufferStart = subMesh._subIndexBufferStart;
|
||
var subIndexBufferCount = subMesh._subIndexBufferCount;
|
||
var boneIndicesList = subMesh._boneIndicesList;
|
||
subIndexBufferStart.length = 1;
|
||
subIndexBufferCount.length = 1;
|
||
boneIndicesList.length = 1;
|
||
subIndexBufferStart[0] = 0;
|
||
subIndexBufferCount[0] = indexBuffer.indexCount;
|
||
var subMeshes = [];
|
||
subMeshes.push(subMesh);
|
||
mesh._setSubMeshes(subMeshes);
|
||
mesh.calculateBounds();
|
||
var memorySize = vertexBuffer._byteLength + indexBuffer._byteLength;
|
||
mesh._setCPUMemory(memorySize);
|
||
mesh._setGPUMemory(memorySize);
|
||
return mesh;
|
||
}
|
||
static createBox(long = 1, height = 1, width = 1) {
|
||
var vertexDeclaration = VertexMesh.getVertexDeclaration("POSITION,NORMAL,UV");
|
||
var halfLong = long / 2;
|
||
var halfHeight = height / 2;
|
||
var halfWidth = width / 2;
|
||
var vertices = new Float32Array([
|
||
-halfLong, halfHeight, -halfWidth, 0, 1, 0, 0, 0, halfLong, halfHeight, -halfWidth, 0, 1, 0, 1, 0, halfLong, halfHeight, halfWidth, 0, 1, 0, 1, 1, -halfLong, halfHeight, halfWidth, 0, 1, 0, 0, 1,
|
||
-halfLong, -halfHeight, -halfWidth, 0, -1, 0, 0, 1, halfLong, -halfHeight, -halfWidth, 0, -1, 0, 1, 1, halfLong, -halfHeight, halfWidth, 0, -1, 0, 1, 0, -halfLong, -halfHeight, halfWidth, 0, -1, 0, 0, 0,
|
||
-halfLong, halfHeight, -halfWidth, -1, 0, 0, 0, 0, -halfLong, halfHeight, halfWidth, -1, 0, 0, 1, 0, -halfLong, -halfHeight, halfWidth, -1, 0, 0, 1, 1, -halfLong, -halfHeight, -halfWidth, -1, 0, 0, 0, 1,
|
||
halfLong, halfHeight, -halfWidth, 1, 0, 0, 1, 0, halfLong, halfHeight, halfWidth, 1, 0, 0, 0, 0, halfLong, -halfHeight, halfWidth, 1, 0, 0, 0, 1, halfLong, -halfHeight, -halfWidth, 1, 0, 0, 1, 1,
|
||
-halfLong, halfHeight, halfWidth, 0, 0, 1, 0, 0, halfLong, halfHeight, halfWidth, 0, 0, 1, 1, 0, halfLong, -halfHeight, halfWidth, 0, 0, 1, 1, 1, -halfLong, -halfHeight, halfWidth, 0, 0, 1, 0, 1,
|
||
-halfLong, halfHeight, -halfWidth, 0, 0, -1, 1, 0, halfLong, halfHeight, -halfWidth, 0, 0, -1, 0, 0, halfLong, -halfHeight, -halfWidth, 0, 0, -1, 0, 1, -halfLong, -halfHeight, -halfWidth, 0, 0, -1, 1, 1
|
||
]);
|
||
var indices = new Uint16Array([
|
||
0, 1, 2, 2, 3, 0,
|
||
4, 7, 6, 6, 5, 4,
|
||
8, 9, 10, 10, 11, 8,
|
||
12, 15, 14, 14, 13, 12,
|
||
16, 17, 18, 18, 19, 16,
|
||
20, 23, 22, 22, 21, 20
|
||
]);
|
||
return PrimitiveMesh._createMesh(vertexDeclaration, vertices, indices);
|
||
}
|
||
static createCapsule(radius = 0.5, height = 2, stacks = 16, slices = 32) {
|
||
var vertexCount = (stacks + 1) * (slices + 1) * 2 + (slices + 1) * 2;
|
||
var indexCount = (3 * stacks * (slices + 1)) * 2 * 2 + 2 * slices * 3;
|
||
var vertexDeclaration = VertexMesh.getVertexDeclaration("POSITION,NORMAL,UV");
|
||
var vertexFloatStride = vertexDeclaration.vertexStride / 4;
|
||
var vertices = new Float32Array(vertexCount * vertexFloatStride);
|
||
var indices = new Uint16Array(indexCount);
|
||
var stackAngle = (Math.PI / 2.0) / stacks;
|
||
var sliceAngle = (Math.PI * 2.0) / slices;
|
||
var hcHeight = height / 2 - radius;
|
||
var posX = 0;
|
||
var posY = 0;
|
||
var posZ = 0;
|
||
var vc = 0;
|
||
var ic = 0;
|
||
var verticeCount = 0;
|
||
var stack, slice;
|
||
for (stack = 0; stack <= stacks; stack++) {
|
||
for (slice = 0; slice <= slices; slice++) {
|
||
posX = radius * Math.cos(stack * stackAngle) * Math.cos(slice * sliceAngle + Math.PI);
|
||
posY = radius * Math.sin(stack * stackAngle);
|
||
posZ = radius * Math.cos(stack * stackAngle) * Math.sin(slice * sliceAngle + Math.PI);
|
||
vertices[vc++] = posX;
|
||
vertices[vc++] = posY + hcHeight;
|
||
vertices[vc++] = posZ;
|
||
vertices[vc++] = posX;
|
||
vertices[vc++] = posY;
|
||
vertices[vc++] = posZ;
|
||
vertices[vc++] = 1 - slice / slices;
|
||
vertices[vc++] = (1 - stack / stacks) * ((Math.PI * radius / 2) / (height + Math.PI * radius));
|
||
if (stack < stacks) {
|
||
indices[ic++] = (stack * (slices + 1)) + slice + (slices + 1);
|
||
indices[ic++] = (stack * (slices + 1)) + slice;
|
||
indices[ic++] = (stack * (slices + 1)) + slice + 1;
|
||
indices[ic++] = (stack * (slices + 1)) + slice + (slices);
|
||
indices[ic++] = (stack * (slices + 1)) + slice;
|
||
indices[ic++] = (stack * (slices + 1)) + slice + (slices + 1);
|
||
}
|
||
}
|
||
}
|
||
verticeCount += (stacks + 1) * (slices + 1);
|
||
for (stack = 0; stack <= stacks; stack++) {
|
||
for (slice = 0; slice <= slices; slice++) {
|
||
posX = radius * Math.cos(stack * stackAngle) * Math.cos(slice * sliceAngle + Math.PI);
|
||
posY = radius * Math.sin(-stack * stackAngle);
|
||
posZ = radius * Math.cos(stack * stackAngle) * Math.sin(slice * sliceAngle + Math.PI);
|
||
vertices[vc++] = posX;
|
||
vertices[vc++] = posY - hcHeight;
|
||
vertices[vc++] = posZ;
|
||
vertices[vc++] = posX;
|
||
vertices[vc++] = posY;
|
||
vertices[vc++] = posZ;
|
||
vertices[vc++] = 1 - slice / slices;
|
||
vertices[vc++] = ((stack / stacks) * (Math.PI * radius / 2) + (height + Math.PI * radius / 2)) / (height + Math.PI * radius);
|
||
if (stack < stacks) {
|
||
indices[ic++] = verticeCount + (stack * (slices + 1)) + slice;
|
||
indices[ic++] = verticeCount + (stack * (slices + 1)) + slice + (slices + 1);
|
||
indices[ic++] = verticeCount + (stack * (slices + 1)) + slice + 1;
|
||
indices[ic++] = verticeCount + (stack * (slices + 1)) + slice;
|
||
indices[ic++] = verticeCount + (stack * (slices + 1)) + slice + (slices);
|
||
indices[ic++] = verticeCount + (stack * (slices + 1)) + slice + (slices + 1);
|
||
}
|
||
}
|
||
}
|
||
verticeCount += (stacks + 1) * (slices + 1);
|
||
for (slice = 0; slice <= slices; slice++) {
|
||
posX = radius * Math.cos(slice * sliceAngle + Math.PI);
|
||
posY = hcHeight;
|
||
posZ = radius * Math.sin(slice * sliceAngle + Math.PI);
|
||
vertices[vc++] = posX;
|
||
vertices[vc + (slices + 1) * 8 - 1] = posX;
|
||
vertices[vc++] = posY;
|
||
vertices[vc + (slices + 1) * 8 - 1] = -posY;
|
||
vertices[vc++] = posZ;
|
||
vertices[vc + (slices + 1) * 8 - 1] = posZ;
|
||
vertices[vc++] = posX;
|
||
vertices[vc + (slices + 1) * 8 - 1] = posX;
|
||
vertices[vc++] = 0;
|
||
vertices[vc + (slices + 1) * 8 - 1] = 0;
|
||
vertices[vc++] = posZ;
|
||
vertices[vc + (slices + 1) * 8 - 1] = posZ;
|
||
vertices[vc++] = 1 - slice * 1 / slices;
|
||
vertices[vc + (slices + 1) * 8 - 1] = 1 - slice * 1 / slices;
|
||
vertices[vc++] = (Math.PI * radius / 2) / (height + Math.PI * radius);
|
||
vertices[vc + (slices + 1) * 8 - 1] = (Math.PI * radius / 2 + height) / (height + Math.PI * radius);
|
||
}
|
||
for (slice = 0; slice < slices; slice++) {
|
||
indices[ic++] = slice + verticeCount + (slices + 1);
|
||
indices[ic++] = slice + verticeCount + 1;
|
||
indices[ic++] = slice + verticeCount;
|
||
indices[ic++] = slice + verticeCount + (slices + 1);
|
||
indices[ic++] = slice + verticeCount + (slices + 1) + 1;
|
||
indices[ic++] = slice + verticeCount + 1;
|
||
}
|
||
verticeCount += 2 * (slices + 1);
|
||
return PrimitiveMesh._createMesh(vertexDeclaration, vertices, indices);
|
||
}
|
||
static createCone(radius = 0.5, height = 1, slices = 32) {
|
||
var vertexCount = (slices + 1 + 1) + (slices + 1) * 2;
|
||
var indexCount = 6 * slices + 3 * slices;
|
||
var vertexDeclaration = VertexMesh.getVertexDeclaration("POSITION,NORMAL,UV");
|
||
var vertexFloatStride = vertexDeclaration.vertexStride / 4;
|
||
var vertices = new Float32Array(vertexCount * vertexFloatStride);
|
||
var indices = new Uint16Array(indexCount);
|
||
var sliceAngle = (Math.PI * 2.0) / slices;
|
||
var halfHeight = height / 2;
|
||
var curAngle = 0;
|
||
var verticeCount = 0;
|
||
var posX = 0;
|
||
var posY = 0;
|
||
var posZ = 0;
|
||
var normal = new Vector3();
|
||
var downV3 = new Vector3(0, -1, 0);
|
||
var upPoint = new Vector3(0, halfHeight, 0);
|
||
var downPoint = new Vector3();
|
||
var v3 = new Vector3();
|
||
var q4 = new Quaternion();
|
||
var rotateAxis = new Vector3();
|
||
var rotateRadius;
|
||
var vc = 0;
|
||
var ic = 0;
|
||
for (var rv = 0; rv <= slices; rv++) {
|
||
curAngle = rv * sliceAngle;
|
||
posX = Math.cos(curAngle + Math.PI) * radius;
|
||
posY = halfHeight;
|
||
posZ = Math.sin(curAngle + Math.PI) * radius;
|
||
vertices[vc++] = 0;
|
||
vertices[vc + (slices + 1) * 8 - 1] = posX;
|
||
vertices[vc++] = posY;
|
||
vertices[vc + (slices + 1) * 8 - 1] = -posY;
|
||
vertices[vc++] = 0;
|
||
vertices[vc + (slices + 1) * 8 - 1] = posZ;
|
||
normal.x = posX;
|
||
normal.y = 0;
|
||
normal.z = posZ;
|
||
downPoint.x = posX;
|
||
downPoint.y = -posY;
|
||
downPoint.z = posZ;
|
||
Vector3.subtract(downPoint, upPoint, v3);
|
||
Vector3.normalize(v3, v3);
|
||
rotateRadius = Math.acos(Vector3.dot(downV3, v3));
|
||
Vector3.cross(downV3, v3, rotateAxis);
|
||
Vector3.normalize(rotateAxis, rotateAxis);
|
||
Quaternion.createFromAxisAngle(rotateAxis, rotateRadius, q4);
|
||
Vector3.normalize(normal, normal);
|
||
Vector3.transformQuat(normal, q4, normal);
|
||
Vector3.normalize(normal, normal);
|
||
vertices[vc++] = normal.x;
|
||
vertices[vc + (slices + 1) * 8 - 1] = normal.x;
|
||
vertices[vc++] = normal.y;
|
||
vertices[vc + (slices + 1) * 8 - 1] = normal.y;
|
||
vertices[vc++] = normal.z;
|
||
vertices[vc + (slices + 1) * 8 - 1] = normal.z;
|
||
vertices[vc++] = 1 - rv * 1 / slices;
|
||
vertices[vc + (slices + 1) * 8 - 1] = 1 - rv * 1 / slices;
|
||
vertices[vc++] = 0;
|
||
vertices[vc + (slices + 1) * 8 - 1] = 1;
|
||
}
|
||
vc += (slices + 1) * 8;
|
||
for (var ri = 0; ri < slices; ri++) {
|
||
indices[ic++] = ri + verticeCount + (slices + 1);
|
||
indices[ic++] = ri + verticeCount + 1;
|
||
indices[ic++] = ri + verticeCount;
|
||
indices[ic++] = ri + verticeCount + (slices + 1);
|
||
indices[ic++] = ri + verticeCount + (slices + 1) + 1;
|
||
indices[ic++] = ri + verticeCount + 1;
|
||
}
|
||
verticeCount += 2 * (slices + 1);
|
||
for (var bv = 0; bv <= slices; bv++) {
|
||
if (bv === 0) {
|
||
vertices[vc++] = 0;
|
||
vertices[vc++] = -halfHeight;
|
||
vertices[vc++] = 0;
|
||
vertices[vc++] = 0;
|
||
vertices[vc++] = -1;
|
||
vertices[vc++] = 0;
|
||
vertices[vc++] = 0.5;
|
||
vertices[vc++] = 0.5;
|
||
}
|
||
curAngle = bv * sliceAngle;
|
||
posX = Math.cos(curAngle + Math.PI) * radius;
|
||
posY = -halfHeight;
|
||
posZ = Math.sin(curAngle + Math.PI) * radius;
|
||
vertices[vc++] = posX;
|
||
vertices[vc++] = posY;
|
||
vertices[vc++] = posZ;
|
||
vertices[vc++] = 0;
|
||
vertices[vc++] = -1;
|
||
vertices[vc++] = 0;
|
||
vertices[vc++] = 0.5 + Math.cos(curAngle) * 0.5;
|
||
vertices[vc++] = 0.5 + Math.sin(curAngle) * 0.5;
|
||
}
|
||
for (var bi = 0; bi < slices; bi++) {
|
||
indices[ic++] = 0 + verticeCount;
|
||
indices[ic++] = bi + 2 + verticeCount;
|
||
indices[ic++] = bi + 1 + verticeCount;
|
||
}
|
||
verticeCount += slices + 1 + 1;
|
||
return PrimitiveMesh._createMesh(vertexDeclaration, vertices, indices);
|
||
}
|
||
static createCylinder(radius = 0.5, height = 2, slices = 32) {
|
||
var vertexCount = (slices + 1 + 1) + (slices + 1) * 2 + (slices + 1 + 1);
|
||
var indexCount = 3 * slices + 6 * slices + 3 * slices;
|
||
var vertexDeclaration = VertexMesh.getVertexDeclaration("POSITION,NORMAL,UV");
|
||
var vertexFloatStride = vertexDeclaration.vertexStride / 4;
|
||
var vertices = new Float32Array(vertexCount * vertexFloatStride);
|
||
var indices = new Uint16Array(indexCount);
|
||
var sliceAngle = (Math.PI * 2.0) / slices;
|
||
var halfHeight = height / 2;
|
||
var curAngle = 0;
|
||
var verticeCount = 0;
|
||
var posX = 0;
|
||
var posY = 0;
|
||
var posZ = 0;
|
||
var vc = 0;
|
||
var ic = 0;
|
||
for (var tv = 0; tv <= slices; tv++) {
|
||
if (tv === 0) {
|
||
vertices[vc++] = 0;
|
||
vertices[vc++] = halfHeight;
|
||
vertices[vc++] = 0;
|
||
vertices[vc++] = 0;
|
||
vertices[vc++] = 1;
|
||
vertices[vc++] = 0;
|
||
vertices[vc++] = 0.5;
|
||
vertices[vc++] = 0.5;
|
||
}
|
||
curAngle = tv * sliceAngle;
|
||
posX = Math.cos(curAngle) * radius;
|
||
posY = halfHeight;
|
||
posZ = Math.sin(curAngle) * radius;
|
||
vertices[vc++] = posX;
|
||
vertices[vc++] = posY;
|
||
vertices[vc++] = posZ;
|
||
vertices[vc++] = 0;
|
||
vertices[vc++] = 1;
|
||
vertices[vc++] = 0;
|
||
vertices[vc++] = 0.5 + Math.cos(curAngle) * 0.5;
|
||
vertices[vc++] = 0.5 + Math.sin(curAngle) * 0.5;
|
||
}
|
||
for (var ti = 0; ti < slices; ti++) {
|
||
indices[ic++] = 0;
|
||
indices[ic++] = ti + 1;
|
||
indices[ic++] = ti + 2;
|
||
}
|
||
verticeCount += slices + 1 + 1;
|
||
for (var rv = 0; rv <= slices; rv++) {
|
||
curAngle = rv * sliceAngle;
|
||
posX = Math.cos(curAngle + Math.PI) * radius;
|
||
posY = halfHeight;
|
||
posZ = Math.sin(curAngle + Math.PI) * radius;
|
||
vertices[vc++] = posX;
|
||
vertices[vc + (slices + 1) * 8 - 1] = posX;
|
||
vertices[vc++] = posY;
|
||
vertices[vc + (slices + 1) * 8 - 1] = -posY;
|
||
vertices[vc++] = posZ;
|
||
vertices[vc + (slices + 1) * 8 - 1] = posZ;
|
||
vertices[vc++] = posX;
|
||
vertices[vc + (slices + 1) * 8 - 1] = posX;
|
||
vertices[vc++] = 0;
|
||
vertices[vc + (slices + 1) * 8 - 1] = 0;
|
||
vertices[vc++] = posZ;
|
||
vertices[vc + (slices + 1) * 8 - 1] = posZ;
|
||
vertices[vc++] = 1 - rv * 1 / slices;
|
||
vertices[vc + (slices + 1) * 8 - 1] = 1 - rv * 1 / slices;
|
||
vertices[vc++] = 0;
|
||
vertices[vc + (slices + 1) * 8 - 1] = 1;
|
||
}
|
||
vc += (slices + 1) * 8;
|
||
for (var ri = 0; ri < slices; ri++) {
|
||
indices[ic++] = ri + verticeCount + (slices + 1);
|
||
indices[ic++] = ri + verticeCount + 1;
|
||
indices[ic++] = ri + verticeCount;
|
||
indices[ic++] = ri + verticeCount + (slices + 1);
|
||
indices[ic++] = ri + verticeCount + (slices + 1) + 1;
|
||
indices[ic++] = ri + verticeCount + 1;
|
||
}
|
||
verticeCount += 2 * (slices + 1);
|
||
for (var bv = 0; bv <= slices; bv++) {
|
||
if (bv === 0) {
|
||
vertices[vc++] = 0;
|
||
vertices[vc++] = -halfHeight;
|
||
vertices[vc++] = 0;
|
||
vertices[vc++] = 0;
|
||
vertices[vc++] = -1;
|
||
vertices[vc++] = 0;
|
||
vertices[vc++] = 0.5;
|
||
vertices[vc++] = 0.5;
|
||
}
|
||
curAngle = bv * sliceAngle;
|
||
posX = Math.cos(curAngle + Math.PI) * radius;
|
||
posY = -halfHeight;
|
||
posZ = Math.sin(curAngle + Math.PI) * radius;
|
||
vertices[vc++] = posX;
|
||
vertices[vc++] = posY;
|
||
vertices[vc++] = posZ;
|
||
vertices[vc++] = 0;
|
||
vertices[vc++] = -1;
|
||
vertices[vc++] = 0;
|
||
vertices[vc++] = 0.5 + Math.cos(curAngle) * 0.5;
|
||
vertices[vc++] = 0.5 + Math.sin(curAngle) * 0.5;
|
||
}
|
||
for (var bi = 0; bi < slices; bi++) {
|
||
indices[ic++] = 0 + verticeCount;
|
||
indices[ic++] = bi + 2 + verticeCount;
|
||
indices[ic++] = bi + 1 + verticeCount;
|
||
}
|
||
verticeCount += slices + 1 + 1;
|
||
return PrimitiveMesh._createMesh(vertexDeclaration, vertices, indices);
|
||
}
|
||
static createPlane(long = 10, width = 10, stacks = 10, slices = 10) {
|
||
var vertexCount = (stacks + 1) * (slices + 1);
|
||
var indexCount = stacks * slices * 2 * 3;
|
||
var indices = new Uint16Array(indexCount);
|
||
var vertexDeclaration = VertexMesh.getVertexDeclaration("POSITION,NORMAL,UV");
|
||
var vertexFloatStride = vertexDeclaration.vertexStride / 4;
|
||
var vertices = new Float32Array(vertexCount * vertexFloatStride);
|
||
var halfLong = long / 2;
|
||
var halfWidth = width / 2;
|
||
var stacksLong = long / stacks;
|
||
var slicesWidth = width / slices;
|
||
var verticeCount = 0;
|
||
for (var i = 0; i <= slices; i++) {
|
||
for (var j = 0; j <= stacks; j++) {
|
||
vertices[verticeCount++] = j * stacksLong - halfLong;
|
||
vertices[verticeCount++] = 0;
|
||
vertices[verticeCount++] = i * slicesWidth - halfWidth;
|
||
vertices[verticeCount++] = 0;
|
||
vertices[verticeCount++] = 1;
|
||
vertices[verticeCount++] = 0;
|
||
vertices[verticeCount++] = j * 1 / stacks;
|
||
vertices[verticeCount++] = i * 1 / slices;
|
||
}
|
||
}
|
||
var indiceIndex = 0;
|
||
for (i = 0; i < slices; i++) {
|
||
for (j = 0; j < stacks; j++) {
|
||
indices[indiceIndex++] = (i + 1) * (stacks + 1) + j;
|
||
indices[indiceIndex++] = i * (stacks + 1) + j;
|
||
indices[indiceIndex++] = (i + 1) * (stacks + 1) + j + 1;
|
||
indices[indiceIndex++] = i * (stacks + 1) + j;
|
||
indices[indiceIndex++] = i * (stacks + 1) + j + 1;
|
||
indices[indiceIndex++] = (i + 1) * (stacks + 1) + j + 1;
|
||
}
|
||
}
|
||
return PrimitiveMesh._createMesh(vertexDeclaration, vertices, indices);
|
||
}
|
||
static createQuad(long = 1, width = 1) {
|
||
var vertexDeclaration = VertexMesh.getVertexDeclaration("POSITION,NORMAL,UV");
|
||
var halfLong = long / 2;
|
||
var halfWidth = width / 2;
|
||
var vertices = new Float32Array([-halfLong, halfWidth, 0, 0, 0, 1, 0, 0, halfLong, halfWidth, 0, 0, 0, 1, 1, 0, -halfLong, -halfWidth, 0, 0, 0, 1, 0, 1, halfLong, -halfWidth, 0, 0, 0, 1, 1, 1]);
|
||
var indices = new Uint16Array([0, 1, 2, 3, 2, 1]);
|
||
return PrimitiveMesh._createMesh(vertexDeclaration, vertices, indices);
|
||
}
|
||
static createSphere(radius = 0.5, stacks = 32, slices = 32) {
|
||
var vertexCount = (stacks + 1) * (slices + 1);
|
||
var indexCount = (3 * stacks * (slices + 1)) * 2;
|
||
var indices = new Uint16Array(indexCount);
|
||
var vertexDeclaration = VertexMesh.getVertexDeclaration("POSITION,NORMAL,UV");
|
||
var vertexFloatStride = vertexDeclaration.vertexStride / 4;
|
||
var vertices = new Float32Array(vertexCount * vertexFloatStride);
|
||
var stackAngle = Math.PI / stacks;
|
||
var sliceAngle = (Math.PI * 2.0) / slices;
|
||
var vertexIndex = 0;
|
||
vertexCount = 0;
|
||
indexCount = 0;
|
||
for (var stack = 0; stack < (stacks + 1); stack++) {
|
||
var r = Math.sin(stack * stackAngle);
|
||
var y = Math.cos(stack * stackAngle);
|
||
for (var slice = 0; slice < (slices + 1); slice++) {
|
||
var x = r * Math.sin(slice * sliceAngle + Math.PI * 1 / 2);
|
||
var z = r * Math.cos(slice * sliceAngle + Math.PI * 1 / 2);
|
||
vertices[vertexCount + 0] = x * radius;
|
||
vertices[vertexCount + 1] = y * radius;
|
||
vertices[vertexCount + 2] = z * radius;
|
||
vertices[vertexCount + 3] = x;
|
||
vertices[vertexCount + 4] = y;
|
||
vertices[vertexCount + 5] = z;
|
||
vertices[vertexCount + 6] = slice / slices;
|
||
vertices[vertexCount + 7] = stack / stacks;
|
||
vertexCount += vertexFloatStride;
|
||
if (stack != (stacks - 1)) {
|
||
indices[indexCount++] = vertexIndex + (slices + 1);
|
||
indices[indexCount++] = vertexIndex;
|
||
indices[indexCount++] = vertexIndex + 1;
|
||
indices[indexCount++] = vertexIndex + (slices);
|
||
indices[indexCount++] = vertexIndex;
|
||
indices[indexCount++] = vertexIndex + (slices + 1);
|
||
vertexIndex++;
|
||
}
|
||
}
|
||
}
|
||
return PrimitiveMesh._createMesh(vertexDeclaration, vertices, indices);
|
||
}
|
||
}
|
||
|
||
var BlitScreenPS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\nuniform sampler2D u_MainTex;\r\nvarying vec2 v_Texcoord0;\r\n\r\nvoid main() {\r\n\tgl_FragColor = texture2D(u_MainTex, v_Texcoord0);\r\n}\r\n\r\n";
|
||
|
||
var BlitScreenVS = "#include \"Lighting.glsl\";\r\n#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\nattribute vec4 a_PositionTexcoord;\r\nuniform vec4 u_OffsetScale;\r\nvarying vec2 v_Texcoord0;\r\n\r\nvoid main() {\t\r\n\tgl_Position = vec4(u_OffsetScale.x*2.0-1.0+(a_PositionTexcoord.x+1.0)*u_OffsetScale.z,(1.0-((u_OffsetScale.y*2.0-1.0+(-a_PositionTexcoord.y+1.0)*u_OffsetScale.w)+1.0)/2.0)*2.0-1.0, 0.0, 1.0);\t\r\n\tv_Texcoord0 = a_PositionTexcoord.zw;\r\n\tgl_Position = remapGLPositionZ(gl_Position);\r\n}";
|
||
|
||
var EffectPS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\n#ifdef COLOR\r\n\tvarying vec4 v_Color;\r\n#endif\r\nvarying vec2 v_Texcoord0;\r\n\r\n#ifdef MAINTEXTURE\r\n\tuniform sampler2D u_AlbedoTexture;\r\n#endif\r\n\r\nuniform vec4 u_AlbedoColor;\r\n\r\n#ifdef FOG\r\n\tuniform float u_FogStart;\r\n\tuniform float u_FogRange;\r\n\t#ifdef ADDTIVEFOG\r\n\t#else\r\n\t\tuniform vec3 u_FogColor;\r\n\t#endif\r\n#endif\r\n\r\nvoid main()\r\n{\r\n\tvec4 color = 2.0 * u_AlbedoColor;\r\n\t#ifdef COLOR\r\n\t\tcolor *= v_Color;\r\n\t#endif\r\n\t#ifdef MAINTEXTURE\r\n\t\tcolor *= texture2D(u_AlbedoTexture, v_Texcoord0);\r\n\t#endif\r\n\t\r\n\tgl_FragColor = color;\r\n\t\r\n\t#ifdef FOG\r\n\t\tfloat lerpFact = clamp((1.0 / gl_FragCoord.w - u_FogStart) / u_FogRange, 0.0, 1.0);\r\n\t\t#ifdef ADDTIVEFOG\r\n\t\t\tgl_FragColor.rgb = mix(gl_FragColor.rgb, vec3(0.0), lerpFact);\r\n\t\t#else\r\n\t\t\tgl_FragColor.rgb = mix(gl_FragColor.rgb, u_FogColor, lerpFact);\r\n\t\t#endif\r\n\t#endif\r\n}\r\n\r\n";
|
||
|
||
var EffectVS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n#include \"Lighting.glsl\";\r\n#include \"LayaUtile.glsl\";\r\n\r\nattribute vec4 a_Position;\r\nattribute vec4 a_Color;\r\nattribute vec2 a_Texcoord0;\r\n\r\n#ifdef GPU_INSTANCE\r\n\tuniform mat4 u_ViewProjection;\r\n\tattribute mat4 a_WorldMat;\r\n#else\r\n\tuniform mat4 u_MvpMatrix;\r\n#endif\r\n\r\n#ifdef COLOR\r\n\tvarying vec4 v_Color;\r\n#endif\r\nvarying vec2 v_Texcoord0;\r\n\r\nuniform vec4 u_TilingOffset;\r\n\r\n#ifdef BONE\r\n\tconst int c_MaxBoneCount = 24;\r\n\tattribute vec4 a_BoneIndices;\r\n\tattribute vec4 a_BoneWeights;\r\n\tuniform mat4 u_Bones[c_MaxBoneCount];\r\n#endif\r\n\r\n\r\nvoid main()\r\n{\r\n\tvec4 position;\r\n\t#ifdef BONE\r\n\t\tmat4 skinTransform;\r\n\t \t#ifdef SIMPLEBONE\r\n\t\t\tfloat currentPixelPos;\r\n\t\t\t#ifdef GPU_INSTANCE\r\n\t\t\t\tcurrentPixelPos = a_SimpleTextureParams.x+a_SimpleTextureParams.y;\r\n\t\t\t#else\r\n\t\t\t\tcurrentPixelPos = u_SimpleAnimatorParams.x+u_SimpleAnimatorParams.y;\r\n\t\t\t#endif\r\n\t\t\tfloat offset = 1.0/u_SimpleAnimatorTextureSize;\r\n\t\t\tskinTransform = loadMatFromTexture(currentPixelPos,int(a_BoneIndices.x),offset) * a_BoneWeights.x;\r\n\t\t\tskinTransform += loadMatFromTexture(currentPixelPos,int(a_BoneIndices.y),offset) * a_BoneWeights.y;\r\n\t\t\tskinTransform += loadMatFromTexture(currentPixelPos,int(a_BoneIndices.z),offset) * a_BoneWeights.z;\r\n\t\t\tskinTransform += loadMatFromTexture(currentPixelPos,int(a_BoneIndices.w),offset) * a_BoneWeights.w;\r\n\t\t#else\r\n\t\t\tskinTransform = u_Bones[int(a_BoneIndices.x)] * a_BoneWeights.x;\r\n\t\t\tskinTransform += u_Bones[int(a_BoneIndices.y)] * a_BoneWeights.y;\r\n\t\t\tskinTransform += u_Bones[int(a_BoneIndices.z)] * a_BoneWeights.z;\r\n\t\t\tskinTransform += u_Bones[int(a_BoneIndices.w)] * a_BoneWeights.w;\r\n\t\t#endif\r\n\t\tposition=skinTransform*a_Position;\r\n\t #else\r\n\t\tposition=a_Position;\r\n\t#endif\r\n\t#ifdef GPU_INSTANCE\r\n\t\tgl_Position = u_ViewProjection * a_WorldMat * position;\r\n\t#else\r\n\t\tgl_Position = u_MvpMatrix * position;\r\n\t#endif\r\n\t\r\n\tv_Texcoord0=TransformUV(a_Texcoord0,u_TilingOffset);\r\n\t\t\r\n\t#ifdef COLOR\r\n\t\tv_Color = a_Color;\r\n\t#endif\r\n\tgl_Position=remapGLPositionZ(gl_Position);\r\n}";
|
||
|
||
var extendTerrainPS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\n#include \"Lighting.glsl\";\r\n\r\n#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(FOG)\r\n\tuniform vec3 u_CameraPos;\r\n\tvarying vec3 v_Normal;\r\n\tvarying vec3 v_PositionWorld;\r\n#endif\r\n\r\n#ifdef FOG\r\n\tuniform float u_FogStart;\r\n\tuniform float u_FogRange;\r\n\tuniform vec3 u_FogColor;\r\n#endif\r\n\r\n#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)\r\n\t#ifdef LEGACYSINGLELIGHTING\r\n\t\t#ifdef DIRECTIONLIGHT\r\n\t\t\tuniform DirectionLight u_DirectionLight;\r\n\t\t#endif\r\n\t\t#ifdef POINTLIGHT\r\n\t\t\tuniform PointLight u_PointLight;\r\n\t\t#endif\r\n\t\t#ifdef SPOTLIGHT\r\n\t\t\tuniform SpotLight u_SpotLight;\r\n\t\t#endif\r\n\t#else\r\n\t\tuniform mat4 u_View;\r\n\t\tuniform vec4 u_ProjectionParams;\r\n\t\tuniform vec4 u_Viewport;\r\n\t\tuniform int u_DirationLightCount;\r\n\t\tuniform sampler2D u_LightBuffer;\r\n\t\tuniform sampler2D u_LightClusterBuffer;\r\n\t#endif\r\n#endif\r\n\r\n#include \"Shadow.glsl\"\r\n#if defined(CALCULATE_SHADOWS)//shader中自定义的宏不可用ifdef 必须改成if defined\r\n\tvarying vec4 v_ShadowCoord;\r\n#endif\r\nvarying float v_posViewZ;\r\n\r\nuniform vec3 u_AmbientColor;\r\n\r\nuniform sampler2D u_SplatAlphaTexture;\r\n\r\nuniform sampler2D u_DiffuseTexture1;\r\nuniform sampler2D u_DiffuseTexture2;\r\nuniform sampler2D u_DiffuseTexture3;\r\nuniform sampler2D u_DiffuseTexture4;\r\nuniform sampler2D u_DiffuseTexture5;\r\n\r\nuniform vec4 u_DiffuseScaleOffset1;\r\nuniform vec4 u_DiffuseScaleOffset2;\r\nuniform vec4 u_DiffuseScaleOffset3;\r\nuniform vec4 u_DiffuseScaleOffset4;\r\nuniform vec4 u_DiffuseScaleOffset5;\r\n\r\nvarying vec2 v_Texcoord0;\r\n\r\n#ifdef LIGHTMAP\r\n\tuniform sampler2D u_LightMap;\r\n\tvarying vec2 v_LightMapUV;\r\n#endif\r\n\r\nvoid main()\r\n{\r\n\tvec4 splatAlpha = vec4(1.0);\r\n\t#ifdef ExtendTerrain_DETAIL_NUM1\r\n\t\tsplatAlpha = texture2D(u_SplatAlphaTexture, v_Texcoord0);\r\n\t\tvec4 color1 = texture2D(u_DiffuseTexture1, v_Texcoord0 * u_DiffuseScaleOffset1.xy);\r\n\t\tgl_FragColor.xyz = color1.xyz * splatAlpha.r;\r\n\t#endif\r\n\t#ifdef ExtendTerrain_DETAIL_NUM2\r\n\t\tsplatAlpha = texture2D(u_SplatAlphaTexture, v_Texcoord0);\r\n\t\tvec4 color1 = texture2D(u_DiffuseTexture1, v_Texcoord0 * u_DiffuseScaleOffset1.xy);\r\n\t\tvec4 color2 = texture2D(u_DiffuseTexture2, v_Texcoord0 * u_DiffuseScaleOffset2.xy);\r\n\t\tgl_FragColor.xyz = color1.xyz * splatAlpha.r + color2.xyz * (1.0 - splatAlpha.r);\r\n\t#endif\r\n\t#ifdef ExtendTerrain_DETAIL_NUM3\r\n\t\tsplatAlpha = texture2D(u_SplatAlphaTexture, v_Texcoord0);\r\n\t\tvec4 color1 = texture2D(u_DiffuseTexture1, v_Texcoord0 * u_DiffuseScaleOffset1.xy);\r\n\t\tvec4 color2 = texture2D(u_DiffuseTexture2, v_Texcoord0 * u_DiffuseScaleOffset2.xy);\r\n\t\tvec4 color3 = texture2D(u_DiffuseTexture3, v_Texcoord0 * u_DiffuseScaleOffset3.xy);\r\n\t\tgl_FragColor.xyz = color1.xyz * splatAlpha.r + color2.xyz * splatAlpha.g + color3.xyz * (1.0 - splatAlpha.r - splatAlpha.g);\r\n\t#endif\r\n\t#ifdef ExtendTerrain_DETAIL_NUM4\r\n\t\tsplatAlpha = texture2D(u_SplatAlphaTexture, v_Texcoord0);\r\n\t\tvec4 color1 = texture2D(u_DiffuseTexture1, v_Texcoord0 * u_DiffuseScaleOffset1.xy);\r\n\t\tvec4 color2 = texture2D(u_DiffuseTexture2, v_Texcoord0 * u_DiffuseScaleOffset2.xy);\r\n\t\tvec4 color3 = texture2D(u_DiffuseTexture3, v_Texcoord0 * u_DiffuseScaleOffset3.xy);\r\n\t\tvec4 color4 = texture2D(u_DiffuseTexture4, v_Texcoord0 * u_DiffuseScaleOffset4.xy);\r\n\t\tgl_FragColor.xyz = color1.xyz * splatAlpha.r + color2.xyz * splatAlpha.g + color3.xyz * splatAlpha.b + color4.xyz * (1.0 - splatAlpha.r - splatAlpha.g - splatAlpha.b);\r\n\t#endif\r\n\t#ifdef ExtendTerrain_DETAIL_NUM5\r\n\t\tsplatAlpha = texture2D(u_SplatAlphaTexture, v_Texcoord0);\r\n\t\tvec4 color1 = texture2D(u_DiffuseTexture1, v_Texcoord0 * u_DiffuseScaleOffset1.xy);\r\n\t\tvec4 color2 = texture2D(u_DiffuseTexture2, v_Texcoord0 * u_DiffuseScaleOffset2.xy);\r\n\t\tvec4 color3 = texture2D(u_DiffuseTexture3, v_Texcoord0 * u_DiffuseScaleOffset3.xy);\r\n\t\tvec4 color4 = texture2D(u_DiffuseTexture4, v_Texcoord0 * u_DiffuseScaleOffset4.xy);\r\n\t\tvec4 color5 = texture2D(u_DiffuseTexture5, v_Texcoord0 * u_DiffuseScaleOffset5.xy);\r\n\t\tgl_FragColor.xyz = color1.xyz * splatAlpha.r + color2.xyz * splatAlpha.g + color3.xyz * splatAlpha.b + color4.xyz * splatAlpha.a + color5.xyz * (1.0 - splatAlpha.r - splatAlpha.g - splatAlpha.b - splatAlpha.a);\r\n\t#endif\r\n\t\tgl_FragColor.w = splatAlpha.a;\r\n\t\t\r\n\t#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)\r\n\t\tvec3 normal = v_Normal;\r\n\t\tvec3 dif, spe;\r\n\t#endif\r\n\r\n\tvec3 diffuse = vec3(0.0);\r\n\tvec3 specular= vec3(0.0);\r\n\t#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(FOG)\r\n\t\tvec3 toEye;\r\n\t\t#ifdef FOG\r\n\t\t\ttoEye=u_CameraPos-v_PositionWorld;\r\n\t\t\tfloat toEyeLength=length(toEye);\r\n\t\t\ttoEye/=toEyeLength;\r\n\t\t#else\r\n\t\t\ttoEye=normalize(u_CameraPos-v_PositionWorld);\r\n\t\t#endif\r\n\t#endif\r\n\r\n\t#ifdef LEGACYSINGLELIGHTING\r\n\t\t#ifdef DIRECTIONLIGHT\r\n\t\t\tLayaAirBlinnPhongDiectionLight(vec3(0.0),1.0,normal,vec3(1.0),toEye,u_DirectionLight,dif,spe);\r\n\t\t\tdiffuse+=dif;\r\n\t\t\tspecular+=spe;\r\n\t\t#endif\r\n\t\r\n\t\t#ifdef POINTLIGHT\r\n\t\t\tLayaAirBlinnPhongPointLight(v_PositionWorld,vec3(0.0),1.0,normal,vec3(1.0),toEye,u_PointLight,dif,spe);\r\n\t\t\tdiffuse+=dif;\r\n\t\t\tspecular+=spe;\r\n\t\t#endif\r\n\r\n\t\t#ifdef SPOTLIGHT\r\n\t\t\tLayaAirBlinnPhongSpotLight(v_PositionWorld,vec3(0.0),1.0,normal,vec3(1.0),toEye,u_SpotLight,dif,spe);\r\n\t\t\tdiffuse+=dif;\r\n\t\t\tspecular+=spe;\r\n\t\t#endif\r\n\t#else\r\n\t\t#ifdef DIRECTIONLIGHT\r\n\t\t\tfor (int i = 0; i < MAX_LIGHT_COUNT; i++) \r\n\t\t\t{\r\n\t\t\t\tif(i >= u_DirationLightCount)\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tDirectionLight directionLight = getDirectionLight(u_LightBuffer,i);\r\n\t\t\t\tLayaAirBlinnPhongDiectionLight(vec3(0.0),1.0,normal,vec3(1.0),toEye,directionLight,dif,spe);\r\n\t\t\t\tdiffuse+=dif;\r\n\t\t\t\tspecular+=spe;\r\n\t\t\t}\r\n\t\t#endif\r\n\t\t#if defined(POINTLIGHT)||defined(SPOTLIGHT)\r\n\t\t\tivec4 clusterInfo =getClusterInfo(u_LightClusterBuffer,u_View,u_Viewport, v_PositionWorld,gl_FragCoord,u_ProjectionParams);\r\n\t\t\t#ifdef POINTLIGHT\r\n\t\t\t\tfor (int i = 0; i < MAX_LIGHT_COUNT; i++) \r\n\t\t\t\t{\r\n\t\t\t\t\tif(i >= clusterInfo.x)//PointLightCount\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tPointLight pointLight = getPointLight(u_LightBuffer,u_LightClusterBuffer,clusterInfo,i);\r\n\t\t\t\t\tLayaAirBlinnPhongPointLight(v_PositionWorld,vec3(0.0),1.0,normal,vec3(1.0),toEye,pointLight,dif,spe);\r\n\t\t\t\t\tdiffuse+=dif;\r\n\t\t\t\t\tspecular+=spe;\r\n\t\t\t\t}\r\n\t\t\t#endif\r\n\t\t\t#ifdef SPOTLIGHT\r\n\t\t\t\tfor (int i = 0; i < MAX_LIGHT_COUNT; i++) \r\n\t\t\t\t{\r\n\t\t\t\t\tif(i >= clusterInfo.y)//SpotLightCount\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tSpotLight spotLight = getSpotLight(u_LightBuffer,u_LightClusterBuffer,clusterInfo,i);\r\n\t\t\t\t\tLayaAirBlinnPhongSpotLight(v_PositionWorld,vec3(0.0),1.0,normal,vec3(1.0),toEye\t,spotLight,dif,spe);\r\n\t\t\t\t\tdiffuse+=dif;\r\n\t\t\t\t\tspecular+=spe;\r\n\t\t\t\t}\r\n\t\t\t#endif\r\n\t\t#endif\r\n\t#endif\r\n\r\nvec3 globalDiffuse = u_AmbientColor;\r\n#ifdef LIGHTMAP\r\n\tglobalDiffuse += decodeHDR(texture2D(u_LightMap, v_LightMapUV),5.0);\r\n#endif\r\n\r\n#if defined(CALCULATE_SHADOWS)//shader中自定义的宏不可用ifdef 必须改成if defined\r\n\tfloat shadowValue = shadowValue = sampleShadowmap(v_ShadowCoord);\r\n\tgl_FragColor = vec4(gl_FragColor.rgb * (globalDiffuse + diffuse) * shadowValue, gl_FragColor.a);\r\n#else\r\n\tgl_FragColor = vec4(gl_FragColor.rgb * (globalDiffuse + diffuse), gl_FragColor.a);\r\n#endif\r\n\r\n#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)\r\n\t#if defined(CALCULATE_SHADOWS)//shader中自定义的宏不可用ifdef 必须改成if defined\r\n\t\tgl_FragColor.rgb += specular * shadowValue;\r\n\t#else\r\n\t\tgl_FragColor.rgb += specular;\r\n\t#endif\r\n#endif\r\n\r\n#ifdef FOG\r\n\tfloat lerpFact=clamp((toEyeLength-u_FogStart)/u_FogRange,0.0,1.0);\r\n\tgl_FragColor.rgb=mix(gl_FragColor.rgb,u_FogColor,lerpFact);\r\n#endif\r\n}\r\n\r\n\r\n\r\n\r\n\r\n";
|
||
|
||
var extendTerrainVS = "#include \"Lighting.glsl\";\r\n\r\nattribute vec4 a_Position;\r\nattribute vec2 a_Texcoord0;\r\n\r\nuniform mat4 u_MvpMatrix;\r\n\r\nvarying vec2 v_Texcoord0;\r\n\r\n#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(LIGHTMAP)\r\n\tattribute vec3 a_Normal;\r\n\tvarying vec3 v_Normal;\r\n#endif\r\n\r\n#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(FOG)||(defined(CALCULATE_SHADOWS)&&defined(SHADOWMAP_PSSM1))\r\n\tuniform mat4 u_WorldMat;\r\n\tvarying vec3 v_PositionWorld;\r\n#endif\r\n\r\n#ifdef LIGHTMAP\r\n\tvarying vec2 v_LightMapUV;\r\n\tuniform vec4 u_LightmapScaleOffset;\r\n#endif\r\n\r\n#if defined(CALCULATE_SHADOWS)//shader<65><72><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD>ĺ겻<C4BA><EAB2BB><EFBFBD><EFBFBD>ifdef <20><><EFBFBD><EFBFBD>ij<EFBFBD>if defined\r\n\tvarying vec4 v_ShadowCoord;\r\n#endif\r\n\r\nvoid main()\r\n{\r\n\tgl_Position = u_MvpMatrix * a_Position;\r\n \r\n\tv_Texcoord0 = a_Texcoord0;\r\n \r\n\t#ifdef LIGHTMAP\r\n\t\tv_LightMapUV = vec2(a_Texcoord0.x, 1.0 - a_Texcoord0.y) * u_LightmapScaleOffset.xy + u_LightmapScaleOffset.zw;\r\n\t\tv_LightMapUV.y = 1.0 - v_LightMapUV.y;\r\n\t#endif\r\n \r\n\t#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)\r\n\t\tv_Normal = a_Normal;\r\n\t#endif\r\n\r\n\t#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(FOG)||(defined(CALCULATE_SHADOWS)&&defined(SHADOWMAP_PSSM1))\r\n\t\tv_PositionWorld=(u_WorldMat*a_Position).xyz;\r\n\t#endif\r\n\r\n\t#if defined(CALCULATE_SHADOWS)//shader<65><72><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD>ĺ겻<C4BA><EAB2BB><EFBFBD><EFBFBD>ifdef <20><><EFBFBD><EFBFBD>ij<EFBFBD>if defined\r\n\t\tv_ShadowCoord = getShadowCoord(vec4(v_PositionWorld));\r\n\t#endif\r\n\tgl_Position=remapGLPositionZ(gl_Position);\r\n}";
|
||
|
||
var GlobalIllumination = "struct LayaGIInput\r\n{\r\n\tvec2 lightmapUV;\r\n\tvec3 worldPos;\r\n};\r\n\r\n#define LAYA_SPECCUBE_LOD_STEPS 6.0\r\n\r\nuniform vec3 u_AmbientColor;\r\n\r\n#if defined(GI_AMBIENT_SH)\r\n\tuniform vec4 u_AmbientSHAr;\r\n\tuniform vec4 u_AmbientSHAg;\r\n\tuniform vec4 u_AmbientSHAb;\r\n\tuniform vec4 u_AmbientSHBr;\r\n\tuniform vec4 u_AmbientSHBg;\r\n\tuniform vec4 u_AmbientSHBb;\r\n\tuniform vec4 u_AmbientSHC;\r\n#endif\r\n\r\nuniform samplerCube u_ReflectTexture;\r\nuniform vec4 u_ReflectCubeHDRParams;\r\n\r\n#ifdef SPECCUBE_BOX_PROJECTION\r\n\tuniform vec3 u_SpecCubeProbePosition;\r\n\tuniform vec3 u_SpecCubeBoxMax;\r\n\tuniform vec3 u_SpecCubeBoxMin;\r\n#endif\r\n\r\n\r\n#ifdef GI_AMBIENT_SH\r\n\tmediump vec3 shEvalLinearL0L1(mediump vec4 normal)\r\n\t{\r\n\t\tmediump vec3 x;\r\n\t\t// Linear (L1) + constant (L0) polynomial terms\r\n\t\tx.r = dot(u_AmbientSHAr, normal);\r\n\t\tx.g = dot(u_AmbientSHAg, normal);\r\n\t\tx.b = dot(u_AmbientSHAb, normal);\r\n\t\treturn x;\r\n\t}\r\n\r\n\tmediump vec3 shEvalLinearL2(mediump vec4 normal)\r\n\t{\r\n\t\tmediump vec3 x1,x2;\r\n\t\t// 4 of the quadratic (L2) polynomials\r\n\t\tmediump vec4 vB = normal.xyzz * normal.yzzx;\r\n\t\tx1.r = dot(u_AmbientSHBr, vB);\r\n\t\tx1.g = dot(u_AmbientSHBg, vB);\r\n\t\tx1.b = dot(u_AmbientSHBb, vB);\r\n\r\n\t\t// Final (5th) quadratic (L2) polynomial\r\n\t\tmediump float vC = normal.x*normal.x - normal.y*normal.y;\r\n\t\tx2 = u_AmbientSHC.rgb * vC;\r\n\r\n\t\treturn x1 + x2;\r\n\t}\r\n\t\r\n\tmediump vec3 shadeSHPerPixel(mediump vec3 normal)\r\n\t{\r\n\t\tmediump vec3 ambientContrib;\r\n\t\tmediump vec4 normalV4=vec4(-normal.x,normal.yz, 1.0);//Note:SH Data is left-hand,so x need inverse\r\n\t\tambientContrib = shEvalLinearL0L1(normalV4);\r\n\t\tambientContrib += shEvalLinearL2(normalV4);\r\n\t\tmediump vec3 ambient = max(vec3(0.0), ambientContrib);\r\n\t\tambient = layaLinearToGammaSpace(ambient);\r\n\t\treturn ambient;\r\n\t}\r\n#endif\r\n\r\n\r\n\r\n mediump vec3 BoxProjectedCubemapDirection(mediump vec3 worldRefl,mediump vec3 worldPos,mediump vec3 cubemapCenter,mediump vec3 boxMin,mediump vec3 boxMax){\r\n\t mediump vec3 nrdir = normalize(worldRefl);\r\n\t mediump vec3 rbmax = (boxMax - worldPos);\r\n\t mediump vec3 rbmin = (boxMin - worldPos);\r\n\t mediump vec3 select = step(vec3(0.0), worldRefl);\r\n\t mediump vec3 rbminmax = mix(rbmin, rbmax, select);\r\n\trbminmax = rbminmax / nrdir;\r\n\tmediump float scalar = min(min(rbminmax.x, rbminmax.y), rbminmax.z);\r\n\t mediump vec3 worldChangeRefl = nrdir * scalar + (worldPos - cubemapCenter);\r\n\treturn worldChangeRefl;\r\n}\r\n\r\n\r\nmediump vec3 layaDecodeDirectionalLightmap (mediump vec3 color, lowp vec4 dirTex, mediump vec3 normalWorld)\r\n{\r\n // In directional (non-specular) mode Enlighten bakes dominant light direction\r\n // in a way, that using it for half Lambert and then dividing by a \"rebalancing coefficient\"\r\n // gives a result close to plain diffuse response lightmaps, but normalmapped.\r\n\r\n // Note that dir is not unit length on purpose. Its length is \"directionality\", like\r\n // for the directional specular lightmaps.\r\n\tlowp vec3 directional=dirTex.xyz - 0.5;\r\n\tdirectional.x=-directional.x;//NOTE:because coord System\r\n mediump float halfLambert = dot(normalWorld,directional) + 0.5;\r\n\r\n return color * halfLambert / max(1e-4, dirTex.w);\r\n}\r\n\r\nvec3 layaGIBase(LayaGIInput giInput,mediump float occlusion, mediump vec3 normalWorld)\r\n{\r\n\tvec3 indirectDiffuse;\r\n\t#ifdef LIGHTMAP\t\r\n\t\tmediump vec3 bakedColor =decodeHDR(texture2D(u_LightMap, giInput.lightmapUV),5.0);\r\n\t\t#ifdef LIGHTMAP_DIRECTIONAL\r\n\t\t\tlowp vec4 bakedDirTex = texture2D (u_LightMapDirection, giInput.lightmapUV);\r\n indirectDiffuse = layaDecodeDirectionalLightmap (bakedColor, bakedDirTex, normalWorld);\r\n\t\t#else //unDirectional lightmap\r\n\t\t\tindirectDiffuse = bakedColor;\r\n\t\t#endif\r\n\t#else\r\n\t\t#ifdef GI_AMBIENT_SH\r\n\t\t\tindirectDiffuse = shadeSHPerPixel(normalWorld);\r\n\t\t#else\r\n\t\t\tindirectDiffuse = u_AmbientColor; //already in gamma space\r\n\t\t#endif\r\n\t#endif\r\n\r\n\tindirectDiffuse*=occlusion;\r\n\treturn indirectDiffuse;\r\n}\r\n\r\nmediump vec3 layaGlossyEnvironment(mediump vec4 glossIn)\r\n{\r\n\tmediump float perceptualRoughness = glossIn.a;\r\n\r\n\t// use approximation to solve,below is more reasonable,but maybe slow. \r\n\t// float m = perceptualRoughnessToRoughness(perceptualRoughness); // m is the real roughness parameter\r\n // const float fEps = 1.192092896e-07F; // smallest such that 1.0+FLT_EPSILON != 1.0 (+1e-4h is NOT good here. is visibly very wrong)\r\n // float n = (2.0/max(fEps, m*m))-2.0; // remap to spec power. See eq. 21 in --> https://dl.dropboxusercontent.com/u/55891920/papers/mm_brdf.pdf\r\n // n /= 4; // remap from n_dot_h formulatino to n_dot_r. See section \"Pre-convolved Cube Maps vs Path Tracers\" --> https://s3.amazonaws.com/docs.knaldtech.com/knald/1.0.0/lys_power_drops.html\r\n // perceptualRoughness = pow( 2/(n+2), 0.25); // remap back to square root of real roughness (0.25 include both the sqrt root of the conversion and sqrt for going from roughness to perceptualRoughness)\r\n\tperceptualRoughness = perceptualRoughness * (1.7 - 0.7*perceptualRoughness);//just a approximation,but fast.\r\n \r\n\tmediump float mip = perceptualRoughness * LAYA_SPECCUBE_LOD_STEPS;\r\n\tmediump vec3 uvw = glossIn.rgb;\r\n\tuvw.x=-uvw.x;//Note:reflectCube is left-hand,so x need inverse\r\n\tmediump vec4 rgbm=textureCubeLodEXT(u_ReflectTexture,uvw,mip);\r\n\treturn decodeHDR(rgbm,u_ReflectCubeHDRParams.x);\r\n}\r\n\r\nmediump vec3 layaGIIndirectSpecular(LayaGIInput giInput,mediump float occlusion, vec4 glossIn)\r\n{\r\n\t#ifdef SPECCUBE_BOX_PROJECTION\r\n\t\tvec3 originalReflUVW = glossIn.xyz;\r\n\t\tglossIn.xyz =BoxProjectedCubemapDirection(originalReflUVW,giInput.worldPos,u_SpecCubeProbePosition,u_SpecCubeBoxMin,u_SpecCubeBoxMax);\r\n\t#endif\r\n\tmediump vec3 specular = layaGlossyEnvironment(glossIn);\r\n\treturn specular * occlusion;\r\n}\r\n\r\n\r\nLayaGI layaGlobalIllumination(LayaGIInput giInput,mediump float occlusion, mediump vec3 normalWorld,mediump vec4 uvwRoughness)\r\n{\r\n\tLayaGI gi;\r\n\tgi.diffuse = layaGIBase(giInput,occlusion, normalWorld);\r\n\tgi.specular = layaGIIndirectSpecular(giInput,occlusion, uvwRoughness);\r\n\treturn gi;\r\n}\r\n\r\n\r\n";
|
||
|
||
var LightingGLSL = "#ifdef GRAPHICS_API_GLES3\r\n\t#define INVERSE_MAT(mat) inverse(mat)\r\n#else\r\n\t#define INVERSE_MAT(mat) inverseMat(mat)\r\n#endif\r\n\r\nstruct DirectionLight {\r\n\tvec3 color;\r\n\tvec3 direction;\r\n};\r\n\r\nstruct PointLight {\r\n\tvec3 color;\r\n\tvec3 position;\r\n\tfloat range;\r\n};\r\n\r\nstruct SpotLight {\r\n\tvec3 color;\r\n\tvec3 position;\r\n\tfloat range;\r\n\tvec3 direction;\r\n\tfloat spot;\r\n};\r\n\r\nstruct LayaGI{\r\n\tvec3 diffuse;\r\n\tvec3 specular;\r\n};\r\n\r\nstruct LayaLight{\r\n\tvec3 color;\r\n\tvec3 dir;\r\n};\r\n\r\nconst int c_ClusterBufferWidth = CLUSTER_X_COUNT*CLUSTER_Y_COUNT;\r\nconst int c_ClusterBufferHeight = CLUSTER_Z_COUNT*(1+int(ceil(float(MAX_LIGHT_COUNT_PER_CLUSTER)/4.0)));\r\nconst int c_ClusterBufferFloatWidth = c_ClusterBufferWidth*4;\r\n\r\n#ifndef GRAPHICS_API_GLES3\r\n\tmat2 inverseMat(mat2 m) {\r\n\t\treturn mat2(m[1][1],-m[0][1],\r\n\t\t\t\t-m[1][0], m[0][0]) / (m[0][0]*m[1][1] - m[0][1]*m[1][0]);\r\n\t}\r\n\tmat3 inverseMat(mat3 m) {\r\n\t\tfloat a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];\r\n\t\tfloat a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];\r\n\t\tfloat a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];\r\n\r\n\t\tfloat b01 = a22 * a11 - a12 * a21;\r\n\t\tfloat b11 = -a22 * a10 + a12 * a20;\r\n\t\tfloat b21 = a21 * a10 - a11 * a20;\r\n\r\n\t\tfloat det = a00 * b01 + a01 * b11 + a02 * b21;\r\n\r\n\t\treturn mat3(b01, (-a22 * a01 + a02 * a21), (a12 * a01 - a02 * a11),\r\n\t\t\t\t\tb11, (a22 * a00 - a02 * a20), (-a12 * a00 + a02 * a10),\r\n\t\t\t\t\tb21, (-a21 * a00 + a01 * a20), (a11 * a00 - a01 * a10)) / det;\r\n\t}\r\n\tmat4 inverseMat(mat4 m) {\r\n\t\tfloat\r\n\t\t\ta00 = m[0][0], a01 = m[0][1], a02 = m[0][2], a03 = m[0][3],\r\n\t\t\ta10 = m[1][0], a11 = m[1][1], a12 = m[1][2], a13 = m[1][3],\r\n\t\t\ta20 = m[2][0], a21 = m[2][1], a22 = m[2][2], a23 = m[2][3],\r\n\t\t\ta30 = m[3][0], a31 = m[3][1], a32 = m[3][2], a33 = m[3][3],\r\n\r\n\t\t\tb00 = a00 * a11 - a01 * a10,\r\n\t\t\tb01 = a00 * a12 - a02 * a10,\r\n\t\t\tb02 = a00 * a13 - a03 * a10,\r\n\t\t\tb03 = a01 * a12 - a02 * a11,\r\n\t\t\tb04 = a01 * a13 - a03 * a11,\r\n\t\t\tb05 = a02 * a13 - a03 * a12,\r\n\t\t\tb06 = a20 * a31 - a21 * a30,\r\n\t\t\tb07 = a20 * a32 - a22 * a30,\r\n\t\t\tb08 = a20 * a33 - a23 * a30,\r\n\t\t\tb09 = a21 * a32 - a22 * a31,\r\n\t\t\tb10 = a21 * a33 - a23 * a31,\r\n\t\t\tb11 = a22 * a33 - a23 * a32,\r\n\r\n\t\t\tdet = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\r\n\r\n\t\treturn mat4(\r\n\t\t\ta11 * b11 - a12 * b10 + a13 * b09,\r\n\t\t\ta02 * b10 - a01 * b11 - a03 * b09,\r\n\t\t\ta31 * b05 - a32 * b04 + a33 * b03,\r\n\t\t\ta22 * b04 - a21 * b05 - a23 * b03,\r\n\t\t\ta12 * b08 - a10 * b11 - a13 * b07,\r\n\t\t\ta00 * b11 - a02 * b08 + a03 * b07,\r\n\t\t\ta32 * b02 - a30 * b05 - a33 * b01,\r\n\t\t\ta20 * b05 - a22 * b02 + a23 * b01,\r\n\t\t\ta10 * b10 - a11 * b08 + a13 * b06,\r\n\t\t\ta01 * b08 - a00 * b10 - a03 * b06,\r\n\t\t\ta30 * b04 - a31 * b02 + a33 * b00,\r\n\t\t\ta21 * b02 - a20 * b04 - a23 * b00,\r\n\t\t\ta11 * b07 - a10 * b09 - a12 * b06,\r\n\t\t\ta00 * b09 - a01 * b07 + a02 * b06,\r\n\t\t\ta31 * b01 - a30 * b03 - a32 * b00,\r\n\t\t\ta20 * b03 - a21 * b01 + a22 * b00) / det;\r\n\t}\r\n#endif\r\n\r\n\t#ifdef THICKNESSMAP\r\n\t\tuniform sampler2D u_ThinknessTexture;\r\n\t#endif\r\n#ifdef ENABLETRANSMISSION\r\n\tuniform float u_TransmissionRate;\r\n\tuniform float u_BackDiffuse;\r\n\tuniform float u_BackScale;\r\n\tuniform vec4 u_TransmissionColor;\r\n\r\n\r\n\tvec3 SubSurfaceIBack(vec3 lightDir,vec3 viewDir,float thinknessFactor){\r\n\t\tvec3 H = normalize(lightDir);\r\n\t\tfloat VdotH = pow(clamp(dot(viewDir,H),0.0,1.0),u_BackDiffuse)*u_BackScale;\r\n\t\tvec3 I;\r\n\t\t#ifdef THICKNESSMAP\r\n\t\t\tI = u_TransmissionColor.rgb*VdotH*thinknessFactor;\r\n\t\t#else\r\n\t\t\tI = u_TransmissionColor.rgb*VdotH;\r\n\t\t#endif\r\n\t\treturn I;\r\n\t}\r\n#endif\r\n\r\nivec4 getClusterInfo(sampler2D clusterBuffer,mat4 viewMatrix,vec4 viewport,vec3 position,vec4 fragCoord,vec4 projectParams)\r\n{\r\n\tvec3 viewPos = vec3(viewMatrix*vec4(position, 1.0)); //position in viewspace\r\n\r\n\tint clusterXIndex = int(floor(fragCoord.x/ (float(viewport.z)/float(CLUSTER_X_COUNT))));\r\n int clusterYIndex = int(floor((viewport.w * (projectParams.z <0.0? 0.0 : 1.0) - fragCoord.y * projectParams.z)/ (float(viewport.w)/float(CLUSTER_Y_COUNT))));//Maybe Flipped ProjectMatrix\r\n\tfloat zSliceParam =float(CLUSTER_Z_COUNT)/log2(projectParams.y / projectParams.x);\r\n \tint clusterZIndex = int(floor(log2(-viewPos.z) * zSliceParam- log2(projectParams.x) * zSliceParam));//projectParams x:cameraNear y:cameraFar\r\n\r\n\tvec2 uv= vec2((float(clusterXIndex + clusterYIndex * CLUSTER_X_COUNT)+0.5)/float(c_ClusterBufferWidth),\r\n\t\t\t\t(float(clusterZIndex)+0.5)/float(c_ClusterBufferHeight));\r\n\tvec4 clusterPixel=texture2D(clusterBuffer, uv);\r\n\treturn ivec4(clusterPixel);//X:Point Count Y:Spot Count Z、W:Light Offset\r\n}\r\n\r\n\r\nint getLightIndex(sampler2D clusterBuffer,int offset,int index) \r\n{\r\n\tint totalOffset=offset+index;\r\n\tint row=totalOffset/c_ClusterBufferFloatWidth;\r\n\tint lastRowFloat=totalOffset-row*c_ClusterBufferFloatWidth;\r\n\tint col=lastRowFloat/4;\r\n\tvec2 uv=vec2((float(col)+0.5)/float(c_ClusterBufferWidth),\r\n\t\t\t\t(float(row)+0.5)/float(c_ClusterBufferHeight));\r\n\tvec4 texel = texture2D(clusterBuffer, uv);\r\n int pixelComponent = lastRowFloat-col*4;\r\n if (pixelComponent == 0) \r\n return int(texel.x);\r\n else if (pixelComponent == 1) \r\n return int(texel.y);\r\n else if (pixelComponent == 2) \r\n return int(texel.z);\r\n else //pixelComponent==3\r\n return int(texel.w);\r\n}\r\n\r\nDirectionLight getDirectionLight(sampler2D lightBuffer,int index) \r\n{\r\n DirectionLight light;\r\n float v = (float(index)+0.5)/ float(MAX_LIGHT_COUNT);\r\n vec4 p1 = texture2D(lightBuffer, vec2(0.125,v));\r\n vec4 p2 = texture2D(lightBuffer, vec2(0.375,v));\r\n\tlight.color=p1.rgb;\r\n light.direction = p2.rgb;\r\n return light;\r\n}\r\n\r\nPointLight getPointLight(sampler2D lightBuffer,sampler2D clusterBuffer,ivec4 clusterInfo,int index) \r\n{\r\n PointLight light;\r\n\tint pointIndex=getLightIndex(clusterBuffer,clusterInfo.z*c_ClusterBufferFloatWidth+clusterInfo.w,index);\r\n float v = (float(pointIndex)+0.5)/ float(MAX_LIGHT_COUNT);\r\n vec4 p1 = texture2D(lightBuffer, vec2(0.125,v));\r\n vec4 p2 = texture2D(lightBuffer, vec2(0.375,v));\r\n\tlight.color=p1.rgb;\r\n\tlight.range = p1.a;\r\n light.position = p2.rgb;\r\n return light;\r\n}\r\n\r\nSpotLight getSpotLight(sampler2D lightBuffer,sampler2D clusterBuffer,ivec4 clusterInfo,int index) \r\n{\r\n SpotLight light;\r\n\tint spoIndex=getLightIndex(clusterBuffer,clusterInfo.z*c_ClusterBufferFloatWidth+clusterInfo.w,clusterInfo.x+index);\r\n float v = (float(spoIndex)+0.5)/ float(MAX_LIGHT_COUNT);\r\n vec4 p1 = texture2D(lightBuffer, vec2(0.125,v));\r\n vec4 p2 = texture2D(lightBuffer, vec2(0.375,v));\r\n\tvec4 p3 = texture2D(lightBuffer, vec2(0.625,v));\r\n light.color = p1.rgb;\r\n\tlight.range=p1.a;\r\n light.position = p2.rgb;\r\n\tlight.spot = p2.a;\r\n\tlight.direction = p3.rgb;\r\n return light;\r\n}\r\n\r\n// Laya中使用衰减纹理\r\nfloat LayaAttenuation(in vec3 L,in float invLightRadius) {\r\n\tfloat fRatio = clamp(length(L) * invLightRadius,0.0,1.0);\r\n\tfRatio *= fRatio;\r\n\treturn 1.0 / (1.0 + 25.0 * fRatio)* clamp(4.0*(1.0 - fRatio),0.0,1.0); //fade to black as if 4 pixel texture\r\n}\r\n\r\n// Same as Just Cause 2 and Crysis 2 (you can read GPU Pro 1 book for more information)\r\nfloat BasicAttenuation(in vec3 L,in float invLightRadius) {\r\n\tvec3 distance = L * invLightRadius;\r\n\tfloat attenuation = clamp(1.0 - dot(distance, distance),0.0,1.0); // Equals float attenuation = saturate(1.0f - dot(L, L) / (lightRadius * lightRadius));\r\n\treturn attenuation * attenuation;\r\n}\r\n\r\n// Inspired on http://fools.slindev.com/viewtopic.php?f=11&t=21&view=unread#unread\r\nfloat NaturalAttenuation(in vec3 L,in float invLightRadius) {\r\n\tfloat attenuationFactor = 30.0;\r\n\tvec3 distance = L * invLightRadius;\r\n\tfloat attenuation = dot(distance, distance); // Equals float attenuation = dot(L, L) / (lightRadius * lightRadius);\r\n\tattenuation = 1.0 / (attenuation * attenuationFactor + 1.0);\r\n\t// Second we move down the function therewith it reaches zero at abscissa 1:\r\n\tattenuationFactor = 1.0 / (attenuationFactor + 1.0); //attenuationFactor contains now the value we have to subtract\r\n\tattenuation = max(attenuation - attenuationFactor, 0.0); // The max fixes a bug.\r\n\t// Finally we expand the equation along the y-axis so that it starts with a function value of 1 again.\r\n\tattenuation /= 1.0 - attenuationFactor;\r\n\treturn attenuation;\r\n}\r\n\r\nvoid LayaAirBlinnPhongLight (in vec3 specColor,in float specColorIntensity,in vec3 normal,in vec3 gloss, in vec3 viewDir,in vec3 lightColor, in vec3 lightVec,out vec3 diffuseColor,out vec3 specularColor) {\r\n\tmediump vec3 h = normalize(viewDir-lightVec);\r\n\tlowp float ln = max (0.0, dot (-lightVec,normal));\r\n\tfloat nh = max (0.0, dot (h,normal));\r\n\tdiffuseColor=lightColor * ln;\r\n\tspecularColor=lightColor *specColor*pow (nh, specColorIntensity*128.0) * gloss;\r\n}\r\n\r\nvoid LayaAirBlinnPhongDiectionLight (in vec3 specColor,in float specColorIntensity,in vec3 normal,in vec3 gloss, in vec3 viewDir, in DirectionLight light,float thinknessFactor,out vec3 diffuseColor,out vec3 specularColor,out vec3 transmisColor) {\r\n\tvec3 lightVec=normalize(light.direction);\r\n\tLayaAirBlinnPhongLight(specColor,specColorIntensity,normal,gloss,viewDir,light.color,lightVec,diffuseColor,specularColor);\r\n\t#ifdef ENABLETRANSMISSION\r\n\t\tdiffuseColor *= u_TransmissionRate;\r\n\t\ttransmisColor = SubSurfaceIBack(lightVec, viewDir,thinknessFactor)*light.color.rgb*(1.0-u_TransmissionRate);\r\n\t#endif\r\n}\r\n\r\n\r\nvoid LayaAirBlinnPhongDiectionLight (in vec3 specColor,in float specColorIntensity,in vec3 normal,in vec3 gloss, in vec3 viewDir, in DirectionLight light,out vec3 diffuseColor,out vec3 specularColor) {\r\n\tvec3 lightVec=normalize(light.direction);\r\n\tLayaAirBlinnPhongLight(specColor,specColorIntensity,normal,gloss,viewDir,light.color,lightVec,diffuseColor,specularColor);\r\n}\r\n\r\n\r\nvoid LayaAirBlinnPhongPointLight (in vec3 pos,in vec3 specColor,in float specColorIntensity,in vec3 normal,in vec3 gloss, in vec3 viewDir, in PointLight light,float thinknessFactor,out vec3 diffuseColor,out vec3 specularColor,out vec3 transmisColor) {\r\n\tvec3 lightVec = pos-light.position;\r\n\tLayaAirBlinnPhongLight(specColor,specColorIntensity,normal,gloss,viewDir,light.color,lightVec/length(lightVec),diffuseColor,specularColor);\r\n\tfloat attenuate = LayaAttenuation(lightVec, 1.0/light.range);\r\n\tdiffuseColor *= attenuate;\r\n\tspecularColor*= attenuate;\r\n\t#ifdef ENABLETRANSMISSION\r\n\t\tdiffuseColor *= u_TransmissionRate;\r\n\t\ttransmisColor = SubSurfaceIBack(lightVec, viewDir,thinknessFactor)*light.color.rgb*(1.0-u_TransmissionRate)*attenuate;\r\n\t#endif\r\n}\r\n\r\nvoid LayaAirBlinnPhongPointLight (in vec3 pos,in vec3 specColor,in float specColorIntensity,in vec3 normal,in vec3 gloss, in vec3 viewDir, in PointLight light,out vec3 diffuseColor,out vec3 specularColor) {\r\n\tvec3 lightVec = pos-light.position;\r\n\tLayaAirBlinnPhongLight(specColor,specColorIntensity,normal,gloss,viewDir,light.color,lightVec/length(lightVec),diffuseColor,specularColor);\r\n\tfloat attenuate = LayaAttenuation(lightVec, 1.0/light.range);\r\n\tdiffuseColor *= attenuate;\r\n\tspecularColor*= attenuate;\r\n}\r\n\r\nvoid LayaAirBlinnPhongSpotLight (in vec3 pos,in vec3 specColor,in float specColorIntensity,in vec3 normal,in vec3 gloss, in vec3 viewDir, in SpotLight light,float thinknessFactor,out vec3 diffuseColor,out vec3 specularColor,out vec3 transmisColor) {\r\n\tvec3 lightVec = pos-light.position;\r\n\tvec3 normalLightVec=lightVec/length(lightVec);\r\n\tLayaAirBlinnPhongLight(specColor,specColorIntensity,normal,gloss,viewDir,light.color,normalLightVec,diffuseColor,specularColor);\r\n\tvec2 cosAngles=cos(vec2(light.spot,light.spot*0.5)*0.5);//ConeAttenuation\r\n\tfloat dl=dot(normalize(light.direction),normalLightVec);\r\n\tdl*=smoothstep(cosAngles[0],cosAngles[1],dl);\r\n\tfloat attenuate = LayaAttenuation(lightVec, 1.0/light.range)*dl;\r\n\tdiffuseColor *=attenuate;\r\n\tspecularColor *=attenuate;\r\n\t#ifdef ENABLETRANSMISSION\r\n\t\tdiffuseColor *= u_TransmissionRate;\r\n\t\ttransmisColor = SubSurfaceIBack(lightVec, viewDir,thinknessFactor)*light.color.rgb*(1.0-u_TransmissionRate)*attenuate;\r\n\t#endif\r\n}\r\n\r\nvoid LayaAirBlinnPhongSpotLight (in vec3 pos,in vec3 specColor,in float specColorIntensity,in vec3 normal,in vec3 gloss, in vec3 viewDir, in SpotLight light,out vec3 diffuseColor,out vec3 specularColor) {\r\n\tvec3 lightVec = pos-light.position;\r\n\tvec3 normalLightVec=lightVec/length(lightVec);\r\n\tLayaAirBlinnPhongLight(specColor,specColorIntensity,normal,gloss,viewDir,light.color,normalLightVec,diffuseColor,specularColor);\r\n\tvec2 cosAngles=cos(vec2(light.spot,light.spot*0.5)*0.5);//ConeAttenuation\r\n\tfloat dl=dot(normalize(light.direction),normalLightVec);\r\n\tdl*=smoothstep(cosAngles[0],cosAngles[1],dl);\r\n\tfloat attenuate = LayaAttenuation(lightVec, 1.0/light.range)*dl;\r\n\tdiffuseColor *=attenuate;\r\n\tspecularColor *=attenuate;\r\n}\r\n\r\n\r\n\r\n\r\nvec3 NormalSampleToWorldSpace(vec3 normalMapSample, vec3 unitNormal, vec3 tangent,vec3 binormal) {\r\n\tvec3 normalT =vec3(2.0*normalMapSample.x - 1.0,1.0-2.0*normalMapSample.y,2.0*normalMapSample.z - 1.0);\r\n\tmediump vec3 N = unitNormal;\r\n\tmediump vec3 T = tangent;\r\n\tmediump vec3 B = binormal;\r\n\tmat3 TBN = mat3(T, B, N);\r\n\r\n\t// Transform from tangent space to world space.\r\n\tvec3 bumpedNormal =normalize(TBN*normalT);\r\n\treturn bumpedNormal;\r\n}\r\n\r\nvec3 NormalSampleToWorldSpace1(vec4 normalMapSample, vec3 tangent, vec3 binormal, vec3 unitNormal) {\r\n\tvec3 normalT;\r\n\tnormalT.x = 2.0 * normalMapSample.x - 1.0;\r\n\tnormalT.y = 1.0 - 2.0 * normalMapSample.y;\r\n\tnormalT.z = sqrt(1.0 - clamp(dot(normalT.xy, normalT.xy), 0.0, 1.0));\r\n\r\n\tvec3 T = normalize(tangent);\r\n\tvec3 B = normalize(binormal);\r\n\tvec3 N = normalize(unitNormal);\r\n\tmat3 TBN = mat3(T, B, N);\r\n\r\n\t// Transform from tangent space to world space.\r\n\tvec3 bumpedNormal = TBN * normalize(normalT);\r\n\r\n\treturn bumpedNormal;\r\n}\r\n\r\nvec3 DecodeLightmap(vec4 color) {\r\n\treturn color.rgb*color.a*5.0;\r\n}\r\n\r\nvec3 decodeHDR(vec4 color,float range) {\r\n\treturn color.rgb*color.a*range;\r\n}\r\n\r\nvec2 TransformUV(vec2 texcoord,vec4 tilingOffset) {\r\n\tvec2 transTexcoord=vec2(texcoord.x,texcoord.y-1.0)*tilingOffset.xy+vec2(tilingOffset.z,-tilingOffset.w);\r\n\ttransTexcoord.y+=1.0;\r\n\treturn transTexcoord;\r\n}\r\n\r\nvec4 remapGLPositionZ(vec4 position) {\r\n\tposition.z=position.z * 2.0 - position.w;\r\n\treturn position;\r\n}\r\n\r\nmediump vec3 layaLinearToGammaSpace (mediump vec3 linRGB)\r\n{\r\n linRGB = max(linRGB, vec3(0.0));\r\n // An almost-perfect approximation from http://chilliant.blogspot.com.au/2012/08/srgb-approximations-for-hlsl.html?m=1\r\n return max(1.055 * pow(linRGB,vec3(0.416666667)) - 0.055, 0.0); \r\n}\r\n\r\nLayaLight layaDirectionLightToLight(in DirectionLight light,in float attenuate)\r\n{\r\n\tLayaLight relight;\r\n\trelight.color = light.color*attenuate;\r\n\trelight.dir = light.direction;\r\n\treturn relight;\r\n}\r\n\r\nLayaLight layaPointLightToLight(in vec3 pos,in vec3 normal, in PointLight light,in float attenuate)\r\n{\r\n\tLayaLight relight;\r\n\tvec3 lightVec = pos-light.position;\r\n\tattenuate *= LayaAttenuation(lightVec, 1.0/light.range);\r\n\trelight.color = light.color*attenuate;\r\n\trelight.dir = normalize(lightVec);\r\n\treturn relight;\r\n}\r\n\r\nLayaLight layaSpotLightToLight(in vec3 pos,in vec3 normal, in SpotLight light,in float attenuate)\r\n{\r\n\tLayaLight relight;\r\n\tvec3 lightVec = pos-light.position;\r\n\tvec3 normalLightVec=lightVec/length(lightVec);\r\n\tvec2 cosAngles=cos(vec2(light.spot,light.spot*0.5)*0.5);//ConeAttenuation\r\n\tfloat dl=dot(normalize(light.direction),normalLightVec);\r\n\tdl*=smoothstep(cosAngles[0],cosAngles[1],dl);\r\n\tattenuate *= LayaAttenuation(lightVec, 1.0/light.range)*dl;\r\n\trelight.dir = normalLightVec;\r\n\trelight.color = light.color*attenuate;\r\n\treturn relight;\r\n}\r\n\r\n\r\n\r\n\r\n";
|
||
|
||
var ShadowSampleTentGLSL = "// ------------------------------------------------------------------\r\n// PCF Filtering Tent Functions\r\n// ------------------------------------------------------------------\r\n\r\n// Assuming a isoceles right angled triangle of height \"triangleHeight\" (as drawn below).\r\n// This function return the area of the triangle above the first texel(in Y the first texel).\r\n//\r\n// |\\ <-- 45 degree slop isosceles right angled triangle\r\n// | \\\r\n// ---- <-- length of this side is \"triangleHeight\"\r\n// _ _ _ _ <-- texels\r\nfloat sampleShadowGetIRTriangleTexelArea(float triangleHeight)\r\n{\r\n return triangleHeight - 0.5;\r\n}\r\n\r\n// Assuming a isoceles triangle of 1.5 texels height and 3 texels wide lying on 4 texels.\r\n// This function return the area of the triangle above each of those texels.\r\n// | <-- offset from -0.5 to 0.5, 0 meaning triangle is exactly in the center\r\n// / \\ <-- 45 degree slop isosceles triangle (ie tent projected in 2D)\r\n// / \\\r\n// _ _ _ _ <-- texels\r\n// X Y Z W <-- result indices (in computedArea.xyzw and computedAreaUncut.xyzw)\r\n// Top point at (right,top) in a texel,left bottom point at (middle,middle) in a texel,right bottom point at (middle,middle) in a texel.\r\nvoid sampleShadowGetTexelAreasTent3x3(float offset, out vec4 computedArea, out vec4 computedAreaUncut)\r\n{\r\n // Compute the exterior areas,a and h is same.\r\n float a = offset + 0.5;\r\n float offsetSquaredHalved = a * a * 0.5;\r\n computedAreaUncut.x = computedArea.x = offsetSquaredHalved - offset;\r\n computedAreaUncut.w = computedArea.w = offsetSquaredHalved;\r\n\r\n // Compute the middle areas\r\n // For Y : We find the area in Y of as if the left section of the isoceles triangle would\r\n // intersect the axis between Y and Z (ie where offset = 0).\r\n computedAreaUncut.y = sampleShadowGetIRTriangleTexelArea(1.5 - offset);\r\n // This area is superior to the one we are looking for if (offset < 0) thus we need to\r\n // subtract the area of the triangle defined by (0,1.5-offset), (0,1.5+offset), (-offset,1.5).\r\n float clampedOffsetLeft = min(offset,0.0);\r\n float areaOfSmallLeftTriangle = clampedOffsetLeft * clampedOffsetLeft;\r\n computedArea.y = computedAreaUncut.y - areaOfSmallLeftTriangle;\r\n\r\n // We do the same for the Z but with the right part of the isoceles triangle\r\n computedAreaUncut.z = sampleShadowGetIRTriangleTexelArea(1.5 + offset);\r\n float clampedOffsetRight = max(offset,0.0);\r\n float areaOfSmallRightTriangle = clampedOffsetRight * clampedOffsetRight;\r\n computedArea.z = computedAreaUncut.z - areaOfSmallRightTriangle;\r\n}\r\n\r\n// Assuming a isoceles triangle of 2.5 texel height and 5 texels wide lying on 6 texels.\r\n// This function return the weight of each texels area relative to the full triangle area.\r\n// / \\\r\n// _ _ _ _ _ _ <-- texels\r\n// 0 1 2 3 4 5 <-- computed area indices (in texelsWeights[])\r\n// Top point at (right,top) in a texel,left bottom point at (middle,middle) in a texel,right bottom point at (middle,middle) in a texel.\r\nvoid sampleShadowGetTexelWeightsTent5x5(float offset, out vec3 texelsWeightsA, out vec3 texelsWeightsB)\r\n{\r\n vec4 areaFrom3texelTriangle;\r\n vec4 areaUncutFrom3texelTriangle;\r\n sampleShadowGetTexelAreasTent3x3(offset, areaFrom3texelTriangle, areaUncutFrom3texelTriangle);\r\n\r\n // Triangle slope is 45 degree thus we can almost reuse the result of the 3 texel wide computation.\r\n // the 5 texel wide triangle can be seen as the 3 texel wide one but shifted up by one unit/texel.\r\n // 0.16 is 1/(the triangle area)\r\n texelsWeightsA.x = 0.16 * (areaFrom3texelTriangle.x);\r\n texelsWeightsA.y = 0.16 * (areaUncutFrom3texelTriangle.y);\r\n texelsWeightsA.z = 0.16 * (areaFrom3texelTriangle.y + 1.0);\r\n texelsWeightsB.x = 0.16 * (areaFrom3texelTriangle.z + 1.0);\r\n texelsWeightsB.y = 0.16 * (areaUncutFrom3texelTriangle.z);\r\n texelsWeightsB.z = 0.16 * (areaFrom3texelTriangle.w);\r\n}\r\n\r\n// 5x5 Tent filter (45 degree sloped triangles in U and V)\r\nvoid sampleShadowComputeSamplesTent5x5(vec4 shadowMapTextureTexelSize, vec2 coord, out float fetchesWeights[9], out vec2 fetchesUV[9])\r\n{\r\n // tent base is 5x5 base thus covering from 25 to 36 texels, thus we need 9 bilinear PCF fetches\r\n vec2 tentCenterInTexelSpace = coord.xy * shadowMapTextureTexelSize.zw;\r\n vec2 centerOfFetchesInTexelSpace = floor(tentCenterInTexelSpace + 0.5);\r\n vec2 offsetFromTentCenterToCenterOfFetches = tentCenterInTexelSpace - centerOfFetchesInTexelSpace;\r\n\r\n // find the weight of each texel based on the area of a 45 degree slop tent above each of them.\r\n vec3 texelsWeightsUA, texelsWeightsUB;\r\n vec3 texelsWeightsVA, texelsWeightsVB;\r\n sampleShadowGetTexelWeightsTent5x5(offsetFromTentCenterToCenterOfFetches.x, texelsWeightsUA, texelsWeightsUB);\r\n sampleShadowGetTexelWeightsTent5x5(offsetFromTentCenterToCenterOfFetches.y, texelsWeightsVA, texelsWeightsVB);\r\n\r\n // each fetch will cover a group of 2x2 texels, the weight of each group is the sum of the weights of the texels\r\n vec3 fetchesWeightsU = vec3(texelsWeightsUA.xz, texelsWeightsUB.y) + vec3(texelsWeightsUA.y, texelsWeightsUB.xz);\r\n vec3 fetchesWeightsV = vec3(texelsWeightsVA.xz, texelsWeightsVB.y) + vec3(texelsWeightsVA.y, texelsWeightsVB.xz);\r\n\r\n // move the PCF bilinear fetches to respect texels weights\r\n vec3 fetchesOffsetsU = vec3(texelsWeightsUA.y, texelsWeightsUB.xz) / fetchesWeightsU.xyz + vec3(-2.5,-0.5,1.5);\r\n vec3 fetchesOffsetsV = vec3(texelsWeightsVA.y, texelsWeightsVB.xz) / fetchesWeightsV.xyz + vec3(-2.5,-0.5,1.5);\r\n fetchesOffsetsU *= shadowMapTextureTexelSize.xxx;\r\n fetchesOffsetsV *= shadowMapTextureTexelSize.yyy;\r\n\r\n vec2 bilinearFetchOrigin = centerOfFetchesInTexelSpace * shadowMapTextureTexelSize.xy;\r\n fetchesUV[0] = bilinearFetchOrigin + vec2(fetchesOffsetsU.x, fetchesOffsetsV.x);\r\n fetchesUV[1] = bilinearFetchOrigin + vec2(fetchesOffsetsU.y, fetchesOffsetsV.x);\r\n fetchesUV[2] = bilinearFetchOrigin + vec2(fetchesOffsetsU.z, fetchesOffsetsV.x);\r\n fetchesUV[3] = bilinearFetchOrigin + vec2(fetchesOffsetsU.x, fetchesOffsetsV.y);\r\n fetchesUV[4] = bilinearFetchOrigin + vec2(fetchesOffsetsU.y, fetchesOffsetsV.y);\r\n fetchesUV[5] = bilinearFetchOrigin + vec2(fetchesOffsetsU.z, fetchesOffsetsV.y);\r\n fetchesUV[6] = bilinearFetchOrigin + vec2(fetchesOffsetsU.x, fetchesOffsetsV.z);\r\n fetchesUV[7] = bilinearFetchOrigin + vec2(fetchesOffsetsU.y, fetchesOffsetsV.z);\r\n fetchesUV[8] = bilinearFetchOrigin + vec2(fetchesOffsetsU.z, fetchesOffsetsV.z);\r\n\r\n fetchesWeights[0] = fetchesWeightsU.x * fetchesWeightsV.x;\r\n fetchesWeights[1] = fetchesWeightsU.y * fetchesWeightsV.x;\r\n fetchesWeights[2] = fetchesWeightsU.z * fetchesWeightsV.x;\r\n fetchesWeights[3] = fetchesWeightsU.x * fetchesWeightsV.y;\r\n fetchesWeights[4] = fetchesWeightsU.y * fetchesWeightsV.y;\r\n fetchesWeights[5] = fetchesWeightsU.z * fetchesWeightsV.y;\r\n fetchesWeights[6] = fetchesWeightsU.x * fetchesWeightsV.z;\r\n fetchesWeights[7] = fetchesWeightsU.y * fetchesWeightsV.z;\r\n fetchesWeights[8] = fetchesWeightsU.z * fetchesWeightsV.z;\r\n}";
|
||
|
||
var LayaUtile = "\r\n\r\n//SimpleSkinnedMesh\r\n#ifdef SIMPLEBONE\r\n\t#ifdef GPU_INSTANCE\r\n\t\tattribute vec4 a_SimpleTextureParams;\r\n\t#else\r\n\t\tuniform vec4 u_SimpleAnimatorParams;\r\n\t#endif\r\n\tuniform sampler2D u_SimpleAnimatorTexture;\r\n\r\n\tuniform float u_SimpleAnimatorTextureSize; \r\n#endif\r\n\r\n\r\n#ifdef SIMPLEBONE\r\n\tmat4 loadMatFromTexture(float FramePos,int boneIndices,float offset)\r\n\t{\r\n\t\tvec2 uv;\r\n\t\tfloat PixelPos = FramePos+float(boneIndices)*4.0;\r\n\t\tfloat halfOffset = offset * 0.5;\r\n\t\tfloat uvoffset = PixelPos/u_SimpleAnimatorTextureSize;\r\n\t\tuv.y = floor(uvoffset)*offset+halfOffset;\r\n\t\tuv.x = mod(float(PixelPos),u_SimpleAnimatorTextureSize)*offset+halfOffset;\r\n\t\tvec4 mat0row = texture2D(u_SimpleAnimatorTexture,uv);\r\n\t\tuv.x+=offset;\r\n\t\tvec4 mat1row = texture2D(u_SimpleAnimatorTexture,uv);\r\n\t\tuv.x+=offset;\r\n\t\tvec4 mat2row = texture2D(u_SimpleAnimatorTexture,uv);\r\n\t\tuv.x+=offset;\r\n\t\tvec4 mat3row = texture2D(u_SimpleAnimatorTexture,uv);\r\n\t\tmat4 m =mat4(mat0row.x,mat0row.y,mat0row.z,mat0row.w,\r\n\t\t\t\tmat1row.x,mat1row.y,mat1row.z,mat1row.w,\r\n\t\t\t\tmat2row.x,mat2row.y,mat2row.z,mat2row.w,\r\n\t\t\t\tmat3row.x,mat3row.y,mat3row.z,mat3row.w);\r\n\t\treturn m;\r\n\t}\r\n#endif\r\n\r\n";
|
||
|
||
var linePS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\nprecision highp float;\r\n#else\r\nprecision mediump float;\r\n#endif\r\n\r\nvarying vec4 v_Color;\r\nuniform vec4 u_Color;\r\n\r\nvoid main()\r\n{\r\n gl_FragColor = v_Color * u_Color; \r\n}\r\n\r\n";
|
||
|
||
var lineVS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\nprecision highp float;\r\n#else\r\nprecision mediump float;\r\n#endif\r\n\r\n#include \"Lighting.glsl\";\r\n\r\nattribute vec4 a_Position;\r\nuniform mat4 u_MvpMatrix;\r\nuniform vec4 u_Color;\r\nattribute vec4 a_Color;\r\nvarying vec4 v_Color;\r\n\r\n\r\nvoid main()\r\n{\r\n\tgl_Position = u_MvpMatrix * a_Position;\r\n\tv_Color=a_Color*u_Color;\r\n\tgl_Position=remapGLPositionZ(gl_Position);\r\n}";
|
||
|
||
var MeshBlinnPhongPS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n\tprecision highp int;\r\n#else\r\n\tprecision mediump float;\r\n\tprecision mediump int;\r\n#endif\r\n\r\n\r\n#include \"Lighting.glsl\";\r\n#include \"Shadow.glsl\"\r\n\r\nuniform vec4 u_DiffuseColor;\r\nuniform float u_AlbedoIntensity;\r\n\r\n#if defined(COLOR)&&defined(ENABLEVERTEXCOLOR)\r\n\tvarying vec4 v_Color;\r\n#endif\r\n\r\n#ifdef ALPHATEST\r\n\tuniform float u_AlphaTestValue;\r\n#endif\r\n\r\n#ifdef DIFFUSEMAP\r\n\tuniform sampler2D u_DiffuseTexture;\r\n#endif\r\n\r\n\r\n#if defined(DIFFUSEMAP)||defined(THICKNESSMAP)||((defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT))&&(defined(SPECULARMAP)||defined(NORMALMAP)))\r\n\tvarying vec2 v_Texcoord0;\r\n#endif\r\n\r\n#ifdef LIGHTMAP\r\n\tvarying vec2 v_LightMapUV;\r\n\tuniform sampler2D u_LightMap;\r\n\t#ifdef LIGHTMAP_DIRECTIONAL\r\n\t\tuniform sampler2D u_LightMapDirection;\r\n\t#endif\r\n#endif\r\n\r\nvarying vec3 v_Normal;\r\n#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)\r\n\tvarying vec3 v_ViewDir; \r\n\r\n\tuniform vec3 u_MaterialSpecular;\r\n\tuniform float u_Shininess;\r\n\r\n\t#ifdef LEGACYSINGLELIGHTING\r\n\t\t#ifdef DIRECTIONLIGHT\r\n\t\t\tuniform DirectionLight u_DirectionLight;\r\n\t\t#endif\r\n\t\t#ifdef POINTLIGHT\r\n\t\t\tuniform PointLight u_PointLight;\r\n\t\t#endif\r\n\t\t#ifdef SPOTLIGHT\r\n\t\t\tuniform SpotLight u_SpotLight;\r\n\t\t#endif\r\n\t#else\r\n\t\tuniform mat4 u_View;\r\n\t\tuniform vec4 u_ProjectionParams;\r\n\t\tuniform vec4 u_Viewport;\r\n\t\tuniform int u_DirationLightCount;\r\n\t\tuniform sampler2D u_LightBuffer;\r\n\t\tuniform sampler2D u_LightClusterBuffer;\r\n\t#endif\r\n\r\n\t#ifdef SPECULARMAP \r\n\t\tuniform sampler2D u_SpecularTexture;\r\n\t#endif\r\n#endif\r\n\r\n#ifdef NORMALMAP \r\n\tuniform sampler2D u_NormalTexture;\r\n\tvarying vec3 v_Tangent;\r\n\tvarying vec3 v_Binormal;\r\n#endif\r\n\r\n#ifdef FOG\r\n\tuniform float u_FogStart;\r\n\tuniform float u_FogRange;\r\n\tuniform vec3 u_FogColor;\r\n#endif\r\n\r\n#if defined(POINTLIGHT)||defined(SPOTLIGHT)||(defined(CALCULATE_SHADOWS)&&defined(SHADOW_CASCADE))||defined(CALCULATE_SPOTSHADOWS)\r\n\tvarying vec3 v_PositionWorld;\r\n#endif\r\n\r\n\r\n#include \"GlobalIllumination.glsl\";//\"GlobalIllumination.glsl use uniform should at front of this\r\n\r\n#if defined(CALCULATE_SHADOWS)&&!defined(SHADOW_CASCADE)\r\n\tvarying vec4 v_ShadowCoord;\r\n#endif\r\n\r\n#if defined(CALCULATE_SPOTSHADOWS)//shader中自定义的宏不可用ifdef 必须改成if defined\r\n\tvarying vec4 v_SpotShadowCoord;\r\n#endif\r\n\r\n\r\nvoid main()\r\n{\r\n\tvec3 normal;//light and SH maybe use normal\r\n\t#if defined(NORMALMAP)\r\n\t\tvec3 normalMapSample = texture2D(u_NormalTexture, v_Texcoord0).rgb;\r\n\t\tnormal = normalize(NormalSampleToWorldSpace(normalMapSample, v_Normal, v_Tangent,v_Binormal));\r\n\t#else\r\n\t\tnormal = normalize(v_Normal);\r\n\t#endif\r\n\r\n\t#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)\r\n\t\tvec3 viewDir= normalize(v_ViewDir);\r\n\t#endif\r\n\r\n\tLayaGIInput giInput;\r\n\t#ifdef LIGHTMAP\t\r\n\t\tgiInput.lightmapUV=v_LightMapUV;\r\n\t#endif\r\n\tvec3 globalDiffuse=layaGIBase(giInput,1.0,normal);\r\n\t\r\n\tvec4 mainColor = u_DiffuseColor * u_AlbedoIntensity;\r\n\t#ifdef DIFFUSEMAP\r\n\t\tvec4 difTexColor=texture2D(u_DiffuseTexture, v_Texcoord0);\r\n\t\tmainColor=mainColor*difTexColor;\r\n\t#endif \r\n\t#if defined(COLOR)&&defined(ENABLEVERTEXCOLOR)\r\n\t\tmainColor=mainColor*v_Color;\r\n\t#endif \r\n \r\n\t#ifdef ALPHATEST\r\n\t\tif(mainColor.a<u_AlphaTestValue)\r\n\t\t\tdiscard;\r\n\t#endif\r\n \r\n\t\r\n\tvec3 diffuse = vec3(0.0);\r\n\tvec3 specular= vec3(0.0);\r\n\tvec3 transmissionDiffuse = vec3(0.0);\r\n\t#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)\r\n\t\tvec3 dif,spe,transmis;\r\n\t\tfloat transmissionFactor;\r\n\t\t#ifdef SPECULARMAP\r\n\t\t\tvec3 gloss=texture2D(u_SpecularTexture, v_Texcoord0).rgb;\r\n\t\t#else\r\n\t\t\t#ifdef DIFFUSEMAP\r\n\t\t\t\tvec3 gloss=vec3(difTexColor.a);\r\n\t\t\t#else\r\n\t\t\t\tvec3 gloss=vec3(1.0);\r\n\t\t\t#endif\r\n\t\t#endif\r\n\t\t#ifdef THICKNESSMAP\r\n\t\t\ttransmissionFactor = texture2D(u_ThinknessTexture, v_Texcoord0).r;\r\n\t\t#endif\r\n\t#endif\r\n\r\n\t\r\n\t\r\n\t#ifdef LEGACYSINGLELIGHTING\r\n\t\t#ifdef DIRECTIONLIGHT\r\n\t\t\tLayaAirBlinnPhongDiectionLight(u_MaterialSpecular,u_Shininess,normal,gloss,viewDir,u_DirectionLight,transmissionFactor,dif,spe,transmis);\r\n\t\t\t#if defined(CALCULATE_SHADOWS)//shader中自定义的宏不可用ifdef 必须改成if defined\r\n\t\t\t\t#ifdef SHADOW_CASCADE\r\n\t\t\t\t\tvec4 shadowCoord = getShadowCoord(vec4(v_PositionWorld,1.0));\r\n\t\t\t\t#else\r\n\t\t\t\t\tvec4 shadowCoord = v_ShadowCoord;\r\n\t\t\t\t#endif\r\n\t\t\t\tfloat shadowAttenuation=sampleShadowmap(shadowCoord);\r\n\t\t\t\tdif *= shadowAttenuation;\r\n\t\t\t\tspe *= shadowAttenuation;\r\n\t\t\t\ttransmis *=shadowAttenuation;\r\n\t\t\t#endif\r\n\t\t\tdiffuse+=dif;\r\n\t\t\tspecular+=spe;\r\n\t\t\ttransmissionDiffuse+=transmis;\r\n\t\t#endif\r\n\t\r\n\t\t#ifdef POINTLIGHT\r\n\t\t\tLayaAirBlinnPhongPointLight(v_PositionWorld,u_MaterialSpecular,u_Shininess,normal,gloss,viewDir,u_PointLight,transmissionFactor,dif,spe,transmis);\r\n\t\t\tdiffuse+=dif;\r\n\t\t\tspecular+=spe;\r\n\t\t\ttransmissionDiffuse+=transmis;\r\n\t\t#endif\r\n\r\n\t\t#ifdef SPOTLIGHT\r\n\t\t\tLayaAirBlinnPhongSpotLight(v_PositionWorld,u_MaterialSpecular,u_Shininess,normal,gloss,viewDir,u_SpotLight,transmissionFactor,dif,spe,transmis);\r\n\t\t\t#if defined(CALCULATE_SPOTSHADOWS)//shader中自定义的宏不可用ifdef 必须改成if defined\r\n\t\t\t\tvec4 spotShadowcoord = v_SpotShadowCoord;\r\n\t\t\t\tfloat spotShadowAttenuation = sampleSpotShadowmap(spotShadowcoord);\r\n\t\t\t\tdif *= spotShadowAttenuation;\r\n\t\t\t\tspe *= spotShadowAttenuation;\r\n\t\t\t\ttransmis *=spotShadowAttenuation;\r\n\t\t\t#endif\r\n\t\t\tdiffuse+=dif;\r\n\t\t\tspecular+=spe;\r\n\t\t\ttransmissionDiffuse+=transmis;\r\n\t\t#endif\r\n\t#else\r\n\t\t#ifdef DIRECTIONLIGHT\r\n\t\t\tfor (int i = 0; i < MAX_LIGHT_COUNT; i++) \r\n\t\t\t{\r\n\t\t\t\tif(i >= u_DirationLightCount)\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tDirectionLight directionLight = getDirectionLight(u_LightBuffer,i);\r\n\t\t\t\t#if defined(CALCULATE_SHADOWS)//shader中自定义的宏不可用ifdef 必须改成if defined\r\n\t\t\t\t\tif(i == 0)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t#ifdef SHADOW_CASCADE\r\n\t\t\t\t\t\t\tvec4 shadowCoord = getShadowCoord(vec4(v_PositionWorld,1.0));\r\n\t\t\t\t\t\t#else\r\n\t\t\t\t\t\t\tvec4 shadowCoord = v_ShadowCoord;\r\n\t\t\t\t\t\t#endif\r\n\t\t\t\t\t\tdirectionLight.color *= sampleShadowmap(shadowCoord);\r\n\t\t\t\t\t}\r\n\t\t\t\t#endif\r\n\t\t\t\tLayaAirBlinnPhongDiectionLight(u_MaterialSpecular,u_Shininess,normal,gloss,viewDir,directionLight,transmissionFactor,dif,spe,transmis);\r\n\t\t\t\tdiffuse+=dif;\r\n\t\t\t\tspecular+=spe;\r\n\t\t\t\ttransmissionDiffuse+=transmis;\r\n\t\t\t}\r\n\t\t#endif\r\n\t\t#if defined(POINTLIGHT)||defined(SPOTLIGHT)\r\n\t\t\tivec4 clusterInfo =getClusterInfo(u_LightClusterBuffer,u_View,u_Viewport, v_PositionWorld,gl_FragCoord,u_ProjectionParams);\r\n\t\t\t#ifdef POINTLIGHT\r\n\t\t\t\tfor (int i = 0; i < MAX_LIGHT_COUNT; i++) \r\n\t\t\t\t{\r\n\t\t\t\t\tif(i >= clusterInfo.x)//PointLightCount\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tPointLight pointLight = getPointLight(u_LightBuffer,u_LightClusterBuffer,clusterInfo,i);\r\n\t\t\t\t\tLayaAirBlinnPhongPointLight(v_PositionWorld,u_MaterialSpecular,u_Shininess,normal,gloss,viewDir,pointLight,transmissionFactor,dif,spe,transmis);\r\n\t\t\t\t\tdiffuse+=dif;\r\n\t\t\t\t\tspecular+=spe;\r\n\t\t\t\t\ttransmissionDiffuse+=transmis;\r\n\t\t\t\t}\r\n\t\t\t#endif\r\n\t\t\t#ifdef SPOTLIGHT\r\n\t\t\t\tfor (int i = 0; i < MAX_LIGHT_COUNT; i++) \r\n\t\t\t\t{\r\n\t\t\t\t\tif(i >= clusterInfo.y)//SpotLightCount\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tSpotLight spotLight = getSpotLight(u_LightBuffer,u_LightClusterBuffer,clusterInfo,i);\r\n\t\t\t\t\t#if defined(CALCULATE_SPOTSHADOWS)//shader中自定义的宏不可用ifdef 必须改成if defined\r\n\t\t\t\t\t\tif(i == 0)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tvec4 spotShadowcoord = v_SpotShadowCoord;\r\n\t\t\t\t\t\t\tspotLight.color *= sampleSpotShadowmap(spotShadowcoord);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t#endif\r\n\t\t\t\t\tLayaAirBlinnPhongSpotLight(v_PositionWorld,u_MaterialSpecular,u_Shininess,normal,gloss,viewDir,spotLight,transmissionFactor,dif,spe,transmis);\r\n\t\t\t\t\tdiffuse+=dif;\r\n\t\t\t\t\tspecular+=spe;\r\n\t\t\t\t\ttransmissionDiffuse+=transmis;\r\n\t\t\t\t}\r\n\t\t\t#endif\r\n\t\t#endif\r\n\t#endif\r\n\r\n\tgl_FragColor =vec4(mainColor.rgb*(globalDiffuse + diffuse),mainColor.a);\r\n\r\n\t#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)\r\n\t\tgl_FragColor.rgb+=specular;\r\n\t#endif\r\n\r\n\t#ifdef ENABLETRANSMISSION\r\n\t\tgl_FragColor.rgb+= transmissionDiffuse;\r\n\t#endif\r\n\r\n\t \r\n\t#ifdef FOG\r\n\t\tfloat lerpFact=clamp((1.0/gl_FragCoord.w-u_FogStart)/u_FogRange,0.0,1.0);\r\n\t\tgl_FragColor.rgb=mix(gl_FragColor.rgb,u_FogColor,lerpFact);\r\n\t#endif\r\n\r\n\t//gl_FragColor.rgb =transmissionDiffuse;\r\n}\r\n\r\n";
|
||
|
||
var MeshBlinnPhongVS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n\tprecision highp int;\r\n#else\r\n\tprecision mediump float;\r\n\tprecision mediump int;\r\n#endif\r\n#include \"Lighting.glsl\";\r\n#include \"LayaUtile.glsl\"\r\n#include \"Shadow.glsl\";\r\n\r\n\r\nattribute vec4 a_Position;\r\n\r\n#ifdef GPU_INSTANCE\r\n\tuniform mat4 u_ViewProjection;\r\n#else\r\n\tuniform mat4 u_MvpMatrix;\r\n#endif\r\n\r\n#if defined(DIFFUSEMAP)||defined(THICKNESSMAP)||((defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT))&&(defined(SPECULARMAP)||defined(NORMALMAP)))||(defined(LIGHTMAP)&&defined(UV))\r\n\tattribute vec2 a_Texcoord0;\r\n\tvarying vec2 v_Texcoord0;\r\n#endif\r\n\r\n#if defined(LIGHTMAP)&&defined(UV1)\r\n\tattribute vec2 a_Texcoord1;\r\n#endif\r\n\r\n#ifdef LIGHTMAP\r\n\tuniform vec4 u_LightmapScaleOffset;\r\n\tvarying vec2 v_LightMapUV;\r\n#endif\r\n\r\n#ifdef COLOR\r\n\tattribute vec4 a_Color;\r\n\tvarying vec4 v_Color;\r\n#endif\r\n\r\n#ifdef BONE\r\n\tconst int c_MaxBoneCount = 24;\r\n\tattribute vec4 a_BoneIndices;\r\n\tattribute vec4 a_BoneWeights;\r\n\tuniform mat4 u_Bones[c_MaxBoneCount];\r\n#endif\r\n\r\nattribute vec3 a_Normal;\r\nvarying vec3 v_Normal; \r\n\r\n#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)\r\n\tuniform vec3 u_CameraPos;\r\n\tvarying vec3 v_ViewDir; \r\n#endif\r\n\r\n#if defined(NORMALMAP)\r\n\tattribute vec4 a_Tangent0;\r\n\tvarying vec3 v_Tangent;\r\n\tvarying vec3 v_Binormal;\r\n#endif\r\n\r\n#ifdef GPU_INSTANCE\r\n\tattribute mat4 a_WorldMat;\r\n#else\r\n\tuniform mat4 u_WorldMat;\r\n#endif\r\n\r\n#if defined(POINTLIGHT)||defined(SPOTLIGHT)||(defined(CALCULATE_SHADOWS)&&defined(SHADOW_CASCADE))||defined(CALCULATE_SPOTSHADOWS)\r\n\tvarying vec3 v_PositionWorld;\r\n#endif\r\n\r\n#if defined(CALCULATE_SHADOWS)&&!defined(SHADOW_CASCADE)\r\n\tvarying vec4 v_ShadowCoord;\r\n#endif\r\n\r\n#if defined(CALCULATE_SPOTSHADOWS)//shader中自定义的宏不可用ifdef 必须改成if defined\r\n\tvarying vec4 v_SpotShadowCoord;\r\n#endif\r\n\r\nuniform vec4 u_TilingOffset;\r\n\r\nvoid main()\r\n{\r\n\tvec4 position;\r\n\t#ifdef BONE\r\n\t\tmat4 skinTransform;\r\n\t \t#ifdef SIMPLEBONE\r\n\t\t\tfloat currentPixelPos;\r\n\t\t\t#ifdef GPU_INSTANCE\r\n\t\t\t\tcurrentPixelPos = a_SimpleTextureParams.x+a_SimpleTextureParams.y;\r\n\t\t\t#else\r\n\t\t\t\tcurrentPixelPos = u_SimpleAnimatorParams.x+u_SimpleAnimatorParams.y;\r\n\t\t\t#endif\r\n\t\t\tfloat offset = 1.0/u_SimpleAnimatorTextureSize;\r\n\t\t\tskinTransform = loadMatFromTexture(currentPixelPos,int(a_BoneIndices.x),offset) * a_BoneWeights.x;\r\n\t\t\tskinTransform += loadMatFromTexture(currentPixelPos,int(a_BoneIndices.y),offset) * a_BoneWeights.y;\r\n\t\t\tskinTransform += loadMatFromTexture(currentPixelPos,int(a_BoneIndices.z),offset) * a_BoneWeights.z;\r\n\t\t\tskinTransform += loadMatFromTexture(currentPixelPos,int(a_BoneIndices.w),offset) * a_BoneWeights.w;\r\n\t\t#else\r\n\t\t\tskinTransform = u_Bones[int(a_BoneIndices.x)] * a_BoneWeights.x;\r\n\t\t\tskinTransform += u_Bones[int(a_BoneIndices.y)] * a_BoneWeights.y;\r\n\t\t\tskinTransform += u_Bones[int(a_BoneIndices.z)] * a_BoneWeights.z;\r\n\t\t\tskinTransform += u_Bones[int(a_BoneIndices.w)] * a_BoneWeights.w;\r\n\t\t#endif\r\n\t\tposition=skinTransform*a_Position;\r\n\t #else\r\n\t\tposition=a_Position;\r\n\t#endif\r\n\r\n\r\n\t\r\n\tmat4 worldMat;\r\n\t#ifdef GPU_INSTANCE\r\n\t\tworldMat = a_WorldMat;\r\n\t#else\r\n\t\tworldMat = u_WorldMat;\r\n\t#endif\r\n\r\n\t#ifdef GPU_INSTANCE\r\n\t\tgl_Position = u_ViewProjection * worldMat * position;\r\n\t#else\r\n\t\tgl_Position = u_MvpMatrix * position;\r\n\t#endif\r\n\r\n\tmat3 worldInvMat;\r\n\t#ifdef BONE\r\n\t\tworldInvMat=INVERSE_MAT(mat3(worldMat*skinTransform));\r\n\t#else\r\n\t\tworldInvMat=INVERSE_MAT(mat3(worldMat));\r\n\t#endif \r\n\tv_Normal=normalize(a_Normal*worldInvMat);\r\n\t#if defined(NORMALMAP)\r\n\t\tv_Tangent=normalize(a_Tangent0.xyz*worldInvMat);\r\n\t\tv_Binormal=cross(v_Normal,v_Tangent)*a_Tangent0.w;\r\n\t#endif\r\n\r\n\t#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||(defined(CALCULATE_SHADOWS)&&defined(SHADOW_CASCADE))||defined(CALCULATE_SPOTSHADOWS)\r\n\t\tvec3 positionWS=(worldMat*position).xyz;\r\n\t\t#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)\r\n\t\t\tv_ViewDir = u_CameraPos-positionWS;\r\n\t\t#endif\r\n\t\t#if defined(POINTLIGHT)||defined(SPOTLIGHT)||(defined(CALCULATE_SHADOWS)&&defined(SHADOW_CASCADE))||defined(CALCULATE_SPOTSHADOWS)\r\n\t\t\tv_PositionWorld = positionWS;\r\n\t\t#endif\r\n\t#endif\r\n\r\n\t#if defined(DIFFUSEMAP)||defined(THICKNESSMAP)||((defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT))&&(defined(SPECULARMAP)||defined(NORMALMAP)))\r\n\t\tv_Texcoord0=TransformUV(a_Texcoord0,u_TilingOffset);\r\n\t#endif\r\n\r\n\t#ifdef LIGHTMAP\r\n\t\t#ifdef UV1\r\n\t\t\tv_LightMapUV=vec2(a_Texcoord1.x,1.0-a_Texcoord1.y)*u_LightmapScaleOffset.xy+u_LightmapScaleOffset.zw;\r\n\t\t#else\r\n\t\t\tv_LightMapUV=vec2(a_Texcoord0.x,1.0-a_Texcoord0.y)*u_LightmapScaleOffset.xy+u_LightmapScaleOffset.zw;\r\n\t\t#endif \r\n\t\tv_LightMapUV.y=1.0-v_LightMapUV.y;\r\n\t#endif\r\n\r\n\t#if defined(COLOR)&&defined(ENABLEVERTEXCOLOR)\r\n\t\tv_Color=a_Color;\r\n\t#endif\r\n\r\n\t#if defined(CALCULATE_SHADOWS)&&!defined(SHADOW_CASCADE)\r\n\t\tv_ShadowCoord =getShadowCoord(vec4(positionWS,1.0));\r\n\t#endif\r\n\r\n\t#if defined(CALCULATE_SPOTSHADOWS)//shader中自定义的宏不可用ifdef 必须改成if defined\r\n\t\tv_SpotShadowCoord = u_SpotViewProjectMatrix*vec4(positionWS,1.0);\r\n\t#endif\r\n\r\n\tgl_Position=remapGLPositionZ(gl_Position);\r\n}";
|
||
|
||
var MeshBlinnPhongShadowCasterPS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n\tprecision highp int;\r\n#else\r\n\tprecision mediump float;\r\n\tprecision mediump int;\r\n#endif\r\n\r\n#include \"ShadowCasterFS.glsl\"\r\n\r\nvoid main()\r\n{\r\n\tgl_FragColor=shadowCasterFragment();\r\n}";
|
||
|
||
var MeshBlinnPhongShadowCasterVS = "#include \"ShadowCasterVS.glsl\"\r\n\r\nvoid main()\r\n{\r\n\tvec4 positionCS = shadowCasterVertex();\r\n\tgl_Position=remapGLPositionZ(positionCS);\r\n}";
|
||
|
||
var ParticleShuriKenPS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n precision highp float;\r\n#else\r\n precision mediump float;\r\n#endif\r\n\r\nvarying vec4 v_Color;\r\nvarying vec2 v_TextureCoordinate;\r\nuniform sampler2D u_texture;\r\nuniform vec4 u_Tintcolor;\r\n\r\n#ifdef RENDERMODE_MESH\r\n\tvarying vec4 v_MeshColor;\r\n#endif\r\n\r\n#ifdef FOG\r\n\tuniform float u_FogStart;\r\n\tuniform float u_FogRange;\r\n\t#ifdef ADDTIVEFOG\r\n\t#else\r\n\t\tuniform vec3 u_FogColor;\r\n\t#endif\r\n#endif\r\n\r\n\r\nvoid main()\r\n{\t\r\n\t#ifdef RENDERMODE_MESH\r\n\t\tgl_FragColor=v_MeshColor;\r\n\t#else\r\n\t\tgl_FragColor=vec4(1.0);\t\r\n\t#endif\r\n\t\t\r\n\t#ifdef DIFFUSEMAP\r\n\t\t#ifdef TINTCOLOR\r\n\t\t\tgl_FragColor*=texture2D(u_texture,v_TextureCoordinate)*u_Tintcolor*2.0*v_Color;\r\n\t\t#else\r\n\t\t\tgl_FragColor*=texture2D(u_texture,v_TextureCoordinate)*v_Color;\r\n\t\t#endif\r\n\t#else\r\n\t\t#ifdef TINTCOLOR\r\n\t\t\tgl_FragColor*=u_Tintcolor*2.0*v_Color;\r\n\t\t#else\r\n\t\t\tgl_FragColor*=v_Color;\r\n\t\t#endif\r\n\t#endif\r\n\t\r\n\t#ifdef FOG\r\n\t\tfloat lerpFact=clamp((1.0/gl_FragCoord.w-u_FogStart)/u_FogRange,0.0,1.0);\r\n\t\t#ifdef ADDTIVEFOG\r\n\t\t\tgl_FragColor.rgb=mix(gl_FragColor.rgb,vec3(0.0,0.0,0.0),lerpFact);\r\n\t\t#else\r\n\t\t\tgl_FragColor.rgb=mix(gl_FragColor.rgb,u_FogColor,lerpFact);\r\n\t\t#endif\r\n\t#endif\r\n}";
|
||
|
||
var ParticleShuriKenVS = "// #include \"Lighting.glsl\";\r\n\r\n//修改这里剔除没有用到的光照函数,增加粒子的编译速度\r\nvec2 TransformUV(vec2 texcoord,vec4 tilingOffset) {\r\n\tvec2 transTexcoord=vec2(texcoord.x,texcoord.y-1.0)*tilingOffset.xy+vec2(tilingOffset.z,-tilingOffset.w);\r\n\ttransTexcoord.y+=1.0;\r\n\treturn transTexcoord;\r\n}\r\n\r\nvec4 remapGLPositionZ(vec4 position) {\r\n\tposition.z=position.z * 2.0 - position.w;\r\n\treturn position;\r\n}\r\n\r\n#if defined(GL_FRAGMENT_PRECISION_HIGH)\r\n precision highp float;\r\n#else\r\n precision mediump float;\r\n#endif\r\n\r\n#if defined(SPHERHBILLBOARD)||defined(STRETCHEDBILLBOARD)||defined(HORIZONTALBILLBOARD)||defined(VERTICALBILLBOARD)\r\n\tattribute vec4 a_CornerTextureCoordinate;\r\n#endif\r\n#ifdef RENDERMODE_MESH\r\n\tattribute vec3 a_MeshPosition;\r\n\tattribute vec4 a_MeshColor;\r\n\tattribute vec2 a_MeshTextureCoordinate;\r\n\tvarying vec4 v_MeshColor;\r\n#endif\r\n\r\nattribute vec4 a_ShapePositionStartLifeTime;\r\nattribute vec4 a_DirectionTime;\r\nattribute vec4 a_StartColor;\r\nattribute vec3 a_StartSize;\r\nattribute vec3 a_StartRotation0;\r\nattribute float a_StartSpeed;\r\n#if defined(COLOROVERLIFETIME)||defined(RANDOMCOLOROVERLIFETIME)||defined(SIZEOVERLIFETIMERANDOMCURVES)||defined(SIZEOVERLIFETIMERANDOMCURVESSEPERATE)||defined(ROTATIONOVERLIFETIMERANDOMCONSTANTS)||defined(ROTATIONOVERLIFETIMERANDOMCURVES)\r\n attribute vec4 a_Random0;\r\n#endif\r\n#if defined(TEXTURESHEETANIMATIONRANDOMCURVE)||defined(VELOCITYOVERLIFETIMERANDOMCONSTANT)||defined(VELOCITYOVERLIFETIMERANDOMCURVE)\r\n attribute vec4 a_Random1;\r\n#endif\r\nattribute vec3 a_SimulationWorldPostion;\r\nattribute vec4 a_SimulationWorldRotation;\r\n\r\nvarying vec4 v_Color;\r\n#ifdef DIFFUSEMAP\r\n\tvarying vec2 v_TextureCoordinate;\r\n#endif\r\n\r\nuniform float u_CurrentTime;\r\nuniform vec3 u_Gravity;\r\n\r\nuniform vec3 u_WorldPosition;\r\nuniform vec4 u_WorldRotation;\r\nuniform bool u_ThreeDStartRotation;\r\nuniform int u_ScalingMode;\r\nuniform vec3 u_PositionScale;\r\nuniform vec3 u_SizeScale;\r\nuniform mat4 u_View;\r\nuniform mat4 u_Projection;\r\n\r\n#ifdef STRETCHEDBILLBOARD\r\n\tuniform vec3 u_CameraPos;\r\n#endif\r\nuniform vec3 u_CameraDirection;//TODO:只有几种广告牌模式需要用\r\nuniform vec3 u_CameraUp;\r\n\r\nuniform float u_StretchedBillboardLengthScale;\r\nuniform float u_StretchedBillboardSpeedScale;\r\nuniform int u_SimulationSpace;\r\n\r\n#if defined(VELOCITYOVERLIFETIMECONSTANT)||defined(VELOCITYOVERLIFETIMECURVE)||defined(VELOCITYOVERLIFETIMERANDOMCONSTANT)||defined(VELOCITYOVERLIFETIMERANDOMCURVE)\r\n uniform int u_VOLSpaceType;\r\n#endif\r\n#if defined(VELOCITYOVERLIFETIMECONSTANT)||defined(VELOCITYOVERLIFETIMERANDOMCONSTANT)\r\n uniform vec3 u_VOLVelocityConst;\r\n#endif\r\n#if defined(VELOCITYOVERLIFETIMECURVE)||defined(VELOCITYOVERLIFETIMERANDOMCURVE)\r\n uniform vec2 u_VOLVelocityGradientX[4];//x为key,y为速度\r\n uniform vec2 u_VOLVelocityGradientY[4];//x为key,y为速度\r\n uniform vec2 u_VOLVelocityGradientZ[4];//x为key,y为速度\r\n#endif\r\n#ifdef VELOCITYOVERLIFETIMERANDOMCONSTANT\r\n uniform vec3 u_VOLVelocityConstMax;\r\n#endif\r\n#ifdef VELOCITYOVERLIFETIMERANDOMCURVE\r\n uniform vec2 u_VOLVelocityGradientMaxX[4];//x为key,y为速度\r\n uniform vec2 u_VOLVelocityGradientMaxY[4];//x为key,y为速度\r\n uniform vec2 u_VOLVelocityGradientMaxZ[4];//x为key,y为速度\r\n#endif\r\n\r\n#ifdef COLOROVERLIFETIME\r\n uniform vec4 u_ColorOverLifeGradientColors[4];//x为key,yzw为Color\r\n uniform vec2 u_ColorOverLifeGradientAlphas[4];//x为key,y为Alpha\r\n#endif\r\n#ifdef RANDOMCOLOROVERLIFETIME\r\n uniform vec4 u_ColorOverLifeGradientColors[4];//x为key,yzw为Color\r\n uniform vec2 u_ColorOverLifeGradientAlphas[4];//x为key,y为Alpha\r\n uniform vec4 u_MaxColorOverLifeGradientColors[4];//x为key,yzw为Color\r\n uniform vec2 u_MaxColorOverLifeGradientAlphas[4];//x为key,y为Alpha\r\n#endif\r\n\r\n\r\n#if defined(SIZEOVERLIFETIMECURVE)||defined(SIZEOVERLIFETIMERANDOMCURVES)\r\n uniform vec2 u_SOLSizeGradient[4];//x为key,y为尺寸\r\n#endif\r\n#ifdef SIZEOVERLIFETIMERANDOMCURVES\r\n uniform vec2 u_SOLSizeGradientMax[4];//x为key,y为尺寸\r\n#endif\r\n#if defined(SIZEOVERLIFETIMECURVESEPERATE)||defined(SIZEOVERLIFETIMERANDOMCURVESSEPERATE)\r\n uniform vec2 u_SOLSizeGradientX[4];//x为key,y为尺寸\r\n uniform vec2 u_SOLSizeGradientY[4];//x为key,y为尺寸\r\n uniform vec2 u_SOLSizeGradientZ[4];//x为key,y为尺寸\r\n#endif\r\n#ifdef SIZEOVERLIFETIMERANDOMCURVESSEPERATE\r\n uniform vec2 u_SOLSizeGradientMaxX[4];//x为key,y为尺寸\r\n uniform vec2 u_SOLSizeGradientMaxY[4];//x为key,y为尺寸\r\n uniform vec2 u_SOLSizeGradientMaxZ[4];//x为key,y为尺寸\r\n#endif\r\n\r\n\r\n#ifdef ROTATIONOVERLIFETIME\r\n #if defined(ROTATIONOVERLIFETIMECONSTANT)||defined(ROTATIONOVERLIFETIMERANDOMCONSTANTS)\r\n uniform float u_ROLAngularVelocityConst;\r\n #endif\r\n #ifdef ROTATIONOVERLIFETIMERANDOMCONSTANTS\r\n uniform float u_ROLAngularVelocityConstMax;\r\n #endif\r\n #if defined(ROTATIONOVERLIFETIMECURVE)||defined(ROTATIONOVERLIFETIMERANDOMCURVES)\r\n uniform vec2 u_ROLAngularVelocityGradient[4];//x为key,y为旋转\r\n #endif\r\n #ifdef ROTATIONOVERLIFETIMERANDOMCURVES\r\n uniform vec2 u_ROLAngularVelocityGradientMax[4];//x为key,y为旋转\r\n #endif\r\n#endif\r\n#ifdef ROTATIONOVERLIFETIMESEPERATE\r\n #if defined(ROTATIONOVERLIFETIMECONSTANT)||defined(ROTATIONOVERLIFETIMERANDOMCONSTANTS)\r\n uniform vec3 u_ROLAngularVelocityConstSeprarate;\r\n #endif\r\n #ifdef ROTATIONOVERLIFETIMERANDOMCONSTANTS\r\n uniform vec3 u_ROLAngularVelocityConstMaxSeprarate;\r\n #endif\r\n #if defined(ROTATIONOVERLIFETIMECURVE)||defined(ROTATIONOVERLIFETIMERANDOMCURVES)\r\n uniform vec2 u_ROLAngularVelocityGradientX[4];\r\n uniform vec2 u_ROLAngularVelocityGradientY[4];\r\n uniform vec2 u_ROLAngularVelocityGradientZ[4];\r\n #endif\r\n #ifdef ROTATIONOVERLIFETIMERANDOMCURVES\r\n uniform vec2 u_ROLAngularVelocityGradientMaxX[4];\r\n uniform vec2 u_ROLAngularVelocityGradientMaxY[4];\r\n uniform vec2 u_ROLAngularVelocityGradientMaxZ[4];\r\n\tuniform vec2 u_ROLAngularVelocityGradientMaxW[4];\r\n #endif\r\n#endif\r\n\r\n#if defined(TEXTURESHEETANIMATIONCURVE)||defined(TEXTURESHEETANIMATIONRANDOMCURVE)\r\n uniform float u_TSACycles;\r\n uniform vec2 u_TSASubUVLength;\r\n uniform vec2 u_TSAGradientUVs[4];//x为key,y为frame\r\n#endif\r\n#ifdef TEXTURESHEETANIMATIONRANDOMCURVE\r\n uniform vec2 u_TSAMaxGradientUVs[4];//x为key,y为frame\r\n#endif\r\n\r\nuniform vec4 u_TilingOffset;\r\n\r\nvec3 rotationByEuler(in vec3 vector,in vec3 rot)\r\n{\r\n\tfloat halfRoll = rot.z * 0.5;\r\n float halfPitch = rot.x * 0.5;\r\n\tfloat halfYaw = rot.y * 0.5;\r\n\r\n\tfloat sinRoll = sin(halfRoll);\r\n\tfloat cosRoll = cos(halfRoll);\r\n\tfloat sinPitch = sin(halfPitch);\r\n\tfloat cosPitch = cos(halfPitch);\r\n\tfloat sinYaw = sin(halfYaw);\r\n\tfloat cosYaw = cos(halfYaw);\r\n\r\n\tfloat quaX = (cosYaw * sinPitch * cosRoll) + (sinYaw * cosPitch * sinRoll);\r\n\tfloat quaY = (sinYaw * cosPitch * cosRoll) - (cosYaw * sinPitch * sinRoll);\r\n\tfloat quaZ = (cosYaw * cosPitch * sinRoll) - (sinYaw * sinPitch * cosRoll);\r\n\tfloat quaW = (cosYaw * cosPitch * cosRoll) + (sinYaw * sinPitch * sinRoll);\r\n\t\r\n\t//vec4 q=vec4(quaX,quaY,quaZ,quaW);\r\n\t//vec3 temp = cross(q.xyz, vector) + q.w * vector;\r\n\t//return (cross(temp, -q.xyz) + dot(q.xyz,vector) * q.xyz + q.w * temp);\r\n\t\r\n\tfloat x = quaX + quaX;\r\n float y = quaY + quaY;\r\n float z = quaZ + quaZ;\r\n float wx = quaW * x;\r\n float wy = quaW * y;\r\n float wz = quaW * z;\r\n\tfloat xx = quaX * x;\r\n float xy = quaX * y;\r\n\tfloat xz = quaX * z;\r\n float yy = quaY * y;\r\n float yz = quaY * z;\r\n float zz = quaZ * z;\r\n\r\n return vec3(((vector.x * ((1.0 - yy) - zz)) + (vector.y * (xy - wz))) + (vector.z * (xz + wy)),\r\n ((vector.x * (xy + wz)) + (vector.y * ((1.0 - xx) - zz))) + (vector.z * (yz - wx)),\r\n ((vector.x * (xz - wy)) + (vector.y * (yz + wx))) + (vector.z * ((1.0 - xx) - yy)));\r\n\t\r\n}\r\n\r\n//假定axis已经归一化\r\nvec3 rotationByAxis(in vec3 vector,in vec3 axis, in float angle)\r\n{\r\n\tfloat halfAngle = angle * 0.5;\r\n\tfloat sin = sin(halfAngle);\r\n\t\r\n\tfloat quaX = axis.x * sin;\r\n\tfloat quaY = axis.y * sin;\r\n\tfloat quaZ = axis.z * sin;\r\n\tfloat quaW = cos(halfAngle);\r\n\t\r\n\t//vec4 q=vec4(quaX,quaY,quaZ,quaW);\r\n\t//vec3 temp = cross(q.xyz, vector) + q.w * vector;\r\n\t//return (cross(temp, -q.xyz) + dot(q.xyz,vector) * q.xyz + q.w * temp);\r\n\t\r\n\tfloat x = quaX + quaX;\r\n float y = quaY + quaY;\r\n float z = quaZ + quaZ;\r\n float wx = quaW * x;\r\n float wy = quaW * y;\r\n float wz = quaW * z;\r\n\tfloat xx = quaX * x;\r\n float xy = quaX * y;\r\n\tfloat xz = quaX * z;\r\n float yy = quaY * y;\r\n float yz = quaY * z;\r\n float zz = quaZ * z;\r\n\r\n return vec3(((vector.x * ((1.0 - yy) - zz)) + (vector.y * (xy - wz))) + (vector.z * (xz + wy)),\r\n ((vector.x * (xy + wz)) + (vector.y * ((1.0 - xx) - zz))) + (vector.z * (yz - wx)),\r\n ((vector.x * (xz - wy)) + (vector.y * (yz + wx))) + (vector.z * ((1.0 - xx) - yy)));\r\n\t\r\n}\r\n\r\nvec3 rotationByQuaternions(in vec3 v,in vec4 q) \r\n{\r\n\treturn v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);\r\n}\r\n\r\n \r\n#if defined(VELOCITYOVERLIFETIMECURVE)||defined(VELOCITYOVERLIFETIMERANDOMCURVE)||defined(SIZEOVERLIFETIMECURVE)||defined(SIZEOVERLIFETIMECURVESEPERATE)||defined(SIZEOVERLIFETIMERANDOMCURVES)||defined(SIZEOVERLIFETIMERANDOMCURVESSEPERATE)\r\nfloat getCurValueFromGradientFloat(in vec2 gradientNumbers[4],in float normalizedAge)\r\n{\r\n\tfloat curValue;\r\n\tfor(int i=1;i<4;i++)\r\n\t{\r\n\t\tvec2 gradientNumber=gradientNumbers[i];\r\n\t\tfloat key=gradientNumber.x;\r\n\t\tif(key>=normalizedAge)\r\n\t\t{\r\n\t\t\tvec2 lastGradientNumber=gradientNumbers[i-1];\r\n\t\t\tfloat lastKey=lastGradientNumber.x;\r\n\t\t\tfloat age=(normalizedAge-lastKey)/(key-lastKey);\r\n\t\t\tcurValue=mix(lastGradientNumber.y,gradientNumber.y,age);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\treturn curValue;\r\n}\r\n#endif\r\n\r\n#if defined(VELOCITYOVERLIFETIMECURVE)||defined(VELOCITYOVERLIFETIMERANDOMCURVE)||defined(ROTATIONOVERLIFETIMECURVE)||defined(ROTATIONOVERLIFETIMERANDOMCURVES)\r\nfloat getTotalValueFromGradientFloat(in vec2 gradientNumbers[4],in float normalizedAge)\r\n{\r\n\tfloat totalValue=0.0;\r\n\tfor(int i=1;i<4;i++)\r\n\t{\r\n\t\tvec2 gradientNumber=gradientNumbers[i];\r\n\t\tfloat key=gradientNumber.x;\r\n\t\tvec2 lastGradientNumber=gradientNumbers[i-1];\r\n\t\tfloat lastValue=lastGradientNumber.y;\r\n\t\t\r\n\t\tif(key>=normalizedAge){\r\n\t\t\tfloat lastKey=lastGradientNumber.x;\r\n\t\t\tfloat age=(normalizedAge-lastKey)/(key-lastKey);\r\n\t\t\ttotalValue+=(lastValue+mix(lastValue,gradientNumber.y,age))/2.0*a_ShapePositionStartLifeTime.w*(normalizedAge-lastKey);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\telse{\r\n\t\t\ttotalValue+=(lastValue+gradientNumber.y)/2.0*a_ShapePositionStartLifeTime.w*(key-lastGradientNumber.x);\r\n\t\t}\r\n\t}\r\n\treturn totalValue;\r\n}\r\n#endif\r\n\r\n#if defined(COLOROVERLIFETIME)||defined(RANDOMCOLOROVERLIFETIME)\r\nvec4 getColorFromGradient(in vec2 gradientAlphas[4],in vec4 gradientColors[4],in float normalizedAge)\r\n{\r\n\tvec4 overTimeColor;\r\n\tfor(int i=1;i<4;i++)\r\n\t{\r\n\t\tvec2 gradientAlpha=gradientAlphas[i];\r\n\t\tfloat alphaKey=gradientAlpha.x;\r\n\t\tif(alphaKey>=normalizedAge)\r\n\t\t{\r\n\t\t\tvec2 lastGradientAlpha=gradientAlphas[i-1];\r\n\t\t\tfloat lastAlphaKey=lastGradientAlpha.x;\r\n\t\t\tfloat age=(normalizedAge-lastAlphaKey)/(alphaKey-lastAlphaKey);\r\n\t\t\toverTimeColor.a=mix(lastGradientAlpha.y,gradientAlpha.y,age);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\t\r\n\tfor(int i=1;i<4;i++)\r\n\t{\r\n\t\tvec4 gradientColor=gradientColors[i];\r\n\t\tfloat colorKey=gradientColor.x;\r\n\t\tif(colorKey>=normalizedAge)\r\n\t\t{\r\n\t\t\tvec4 lastGradientColor=gradientColors[i-1];\r\n\t\t\tfloat lastColorKey=lastGradientColor.x;\r\n\t\t\tfloat age=(normalizedAge-lastColorKey)/(colorKey-lastColorKey);\r\n\t\t\toverTimeColor.rgb=mix(gradientColors[i-1].yzw,gradientColor.yzw,age);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\treturn overTimeColor;\r\n}\r\n#endif\r\n\r\n\r\n#if defined(TEXTURESHEETANIMATIONCURVE)||defined(TEXTURESHEETANIMATIONRANDOMCURVE)\r\nfloat getFrameFromGradient(in vec2 gradientFrames[4],in float normalizedAge)\r\n{\r\n\tfloat overTimeFrame;\r\n\tfor(int i=1;i<4;i++)\r\n\t{\r\n\t\tvec2 gradientFrame=gradientFrames[i];\r\n\t\tfloat key=gradientFrame.x;\r\n\t\tif(key>=normalizedAge)\r\n\t\t{\r\n\t\t\tvec2 lastGradientFrame=gradientFrames[i-1];\r\n\t\t\tfloat lastKey=lastGradientFrame.x;\r\n\t\t\tfloat age=(normalizedAge-lastKey)/(key-lastKey);\r\n\t\t\toverTimeFrame=mix(lastGradientFrame.y,gradientFrame.y,age);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\treturn floor(overTimeFrame);\r\n}\r\n#endif\r\n\r\n#if defined(VELOCITYOVERLIFETIMECONSTANT)||defined(VELOCITYOVERLIFETIMECURVE)||defined(VELOCITYOVERLIFETIMERANDOMCONSTANT)||defined(VELOCITYOVERLIFETIMERANDOMCURVE)\r\nvec3 computeParticleLifeVelocity(in float normalizedAge)\r\n{\r\n vec3 outLifeVelocity;\r\n #ifdef VELOCITYOVERLIFETIMECONSTANT\r\n\t outLifeVelocity=u_VOLVelocityConst; \r\n #endif\r\n #ifdef VELOCITYOVERLIFETIMECURVE\r\n outLifeVelocity= vec3(getCurValueFromGradientFloat(u_VOLVelocityGradientX,normalizedAge),getCurValueFromGradientFloat(u_VOLVelocityGradientY,normalizedAge),getCurValueFromGradientFloat(u_VOLVelocityGradientZ,normalizedAge));\r\n #endif\r\n #ifdef VELOCITYOVERLIFETIMERANDOMCONSTANT\r\n\t outLifeVelocity=mix(u_VOLVelocityConst,u_VOLVelocityConstMax,vec3(a_Random1.y,a_Random1.z,a_Random1.w)); \r\n #endif\r\n #ifdef VELOCITYOVERLIFETIMERANDOMCURVE\r\n outLifeVelocity=vec3(mix(getCurValueFromGradientFloat(u_VOLVelocityGradientX,normalizedAge),getCurValueFromGradientFloat(u_VOLVelocityGradientMaxX,normalizedAge),a_Random1.y),\r\n\t mix(getCurValueFromGradientFloat(u_VOLVelocityGradientY,normalizedAge),getCurValueFromGradientFloat(u_VOLVelocityGradientMaxY,normalizedAge),a_Random1.z),\r\n\t\t\t\t\t mix(getCurValueFromGradientFloat(u_VOLVelocityGradientZ,normalizedAge),getCurValueFromGradientFloat(u_VOLVelocityGradientMaxZ,normalizedAge),a_Random1.w));\r\n #endif\r\n\t\t\t\t\t\r\n return outLifeVelocity;\r\n} \r\n#endif\r\n\r\nvec3 computeParticlePosition(in vec3 startVelocity, in vec3 lifeVelocity,in float age,in float normalizedAge,vec3 gravityVelocity,vec4 worldRotation)\r\n{\r\n vec3 startPosition;\r\n vec3 lifePosition;\r\n #if defined(VELOCITYOVERLIFETIMECONSTANT)||defined(VELOCITYOVERLIFETIMECURVE)||defined(VELOCITYOVERLIFETIMERANDOMCONSTANT)||defined(VELOCITYOVERLIFETIMERANDOMCURVE)\r\n\t#ifdef VELOCITYOVERLIFETIMECONSTANT\r\n\t\t startPosition=startVelocity*age;\r\n\t\t lifePosition=lifeVelocity*age;\r\n\t#endif\r\n\t#ifdef VELOCITYOVERLIFETIMECURVE\r\n\t\t startPosition=startVelocity*age;\r\n\t\t lifePosition=vec3(getTotalValueFromGradientFloat(u_VOLVelocityGradientX,normalizedAge),getTotalValueFromGradientFloat(u_VOLVelocityGradientY,normalizedAge),getTotalValueFromGradientFloat(u_VOLVelocityGradientZ,normalizedAge));\r\n\t#endif\r\n\t#ifdef VELOCITYOVERLIFETIMERANDOMCONSTANT\r\n\t\t startPosition=startVelocity*age;\r\n\t\t lifePosition=lifeVelocity*age;\r\n\t#endif\r\n\t#ifdef VELOCITYOVERLIFETIMERANDOMCURVE\r\n\t\t startPosition=startVelocity*age;\r\n\t\t lifePosition=vec3(mix(getTotalValueFromGradientFloat(u_VOLVelocityGradientX,normalizedAge),getTotalValueFromGradientFloat(u_VOLVelocityGradientMaxX,normalizedAge),a_Random1.y)\r\n\t ,mix(getTotalValueFromGradientFloat(u_VOLVelocityGradientY,normalizedAge),getTotalValueFromGradientFloat(u_VOLVelocityGradientMaxY,normalizedAge),a_Random1.z)\r\n\t ,mix(getTotalValueFromGradientFloat(u_VOLVelocityGradientZ,normalizedAge),getTotalValueFromGradientFloat(u_VOLVelocityGradientMaxZ,normalizedAge),a_Random1.w));\r\n\t#endif\r\n\t\r\n\tvec3 finalPosition;\r\n\tif(u_VOLSpaceType==0){\r\n\t if(u_ScalingMode!=2)\r\n\t finalPosition =rotationByQuaternions(u_PositionScale*(a_ShapePositionStartLifeTime.xyz+startPosition+lifePosition),worldRotation);\r\n\t else\r\n\t finalPosition =rotationByQuaternions(u_PositionScale*a_ShapePositionStartLifeTime.xyz+startPosition+lifePosition,worldRotation);\r\n\t}\r\n\telse{\r\n\t if(u_ScalingMode!=2)\r\n\t finalPosition = rotationByQuaternions(u_PositionScale*(a_ShapePositionStartLifeTime.xyz+startPosition),worldRotation)+lifePosition;\r\n\t else\r\n\t finalPosition = rotationByQuaternions(u_PositionScale*a_ShapePositionStartLifeTime.xyz+startPosition,worldRotation)+lifePosition;\r\n\t}\r\n #else\r\n\t startPosition=startVelocity*age;\r\n\t vec3 finalPosition;\r\n\t if(u_ScalingMode!=2)\r\n\t\t\tfinalPosition = rotationByQuaternions(u_PositionScale*(a_ShapePositionStartLifeTime.xyz+startPosition),worldRotation);\r\n\t else\r\n\t \tfinalPosition = rotationByQuaternions(u_PositionScale*a_ShapePositionStartLifeTime.xyz+startPosition,worldRotation);\r\n #endif\r\n \r\n if(u_SimulationSpace==0)\r\n finalPosition=finalPosition+a_SimulationWorldPostion;\r\n else if(u_SimulationSpace==1) \r\n finalPosition=finalPosition+u_WorldPosition;\r\n \r\n finalPosition+=0.5*gravityVelocity*age;\r\n \r\n return finalPosition;\r\n}\r\n\r\n\r\nvec4 computeParticleColor(in vec4 color,in float normalizedAge)\r\n{\r\n\t#ifdef COLOROVERLIFETIME\r\n\t color*=getColorFromGradient(u_ColorOverLifeGradientAlphas,u_ColorOverLifeGradientColors,normalizedAge);\r\n\t#endif\r\n\t\r\n\t#ifdef RANDOMCOLOROVERLIFETIME\r\n\t color*=mix(getColorFromGradient(u_ColorOverLifeGradientAlphas,u_ColorOverLifeGradientColors,normalizedAge),getColorFromGradient(u_MaxColorOverLifeGradientAlphas,u_MaxColorOverLifeGradientColors,normalizedAge),a_Random0.y);\r\n\t#endif\r\n\r\n return color;\r\n}\r\n\r\nvec2 computeParticleSizeBillbard(in vec2 size,in float normalizedAge)\r\n{\r\n\t#ifdef SIZEOVERLIFETIMECURVE\r\n\t\tsize*=getCurValueFromGradientFloat(u_SOLSizeGradient,normalizedAge);\r\n\t#endif\r\n\t#ifdef SIZEOVERLIFETIMERANDOMCURVES\r\n\t size*=mix(getCurValueFromGradientFloat(u_SOLSizeGradient,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientMax,normalizedAge),a_Random0.z); \r\n\t#endif\r\n\t#ifdef SIZEOVERLIFETIMECURVESEPERATE\r\n\t\tsize*=vec2(getCurValueFromGradientFloat(u_SOLSizeGradientX,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientY,normalizedAge));\r\n\t#endif\r\n\t#ifdef SIZEOVERLIFETIMERANDOMCURVESSEPERATE\r\n\t size*=vec2(mix(getCurValueFromGradientFloat(u_SOLSizeGradientX,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientMaxX,normalizedAge),a_Random0.z)\r\n\t ,mix(getCurValueFromGradientFloat(u_SOLSizeGradientY,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientMaxY,normalizedAge),a_Random0.z));\r\n\t#endif\r\n\treturn size;\r\n}\r\n\r\n#ifdef RENDERMODE_MESH\r\nvec3 computeParticleSizeMesh(in vec3 size,in float normalizedAge)\r\n{\r\n\t#ifdef SIZEOVERLIFETIMECURVE\r\n\t\tsize*=getCurValueFromGradientFloat(u_SOLSizeGradient,normalizedAge);\r\n\t#endif\r\n\t#ifdef SIZEOVERLIFETIMERANDOMCURVES\r\n\t size*=mix(getCurValueFromGradientFloat(u_SOLSizeGradient,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientMax,normalizedAge),a_Random0.z); \r\n\t#endif\r\n\t#ifdef SIZEOVERLIFETIMECURVESEPERATE\r\n\t\tsize*=vec3(getCurValueFromGradientFloat(u_SOLSizeGradientX,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientY,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientZ,normalizedAge));\r\n\t#endif\r\n\t#ifdef SIZEOVERLIFETIMERANDOMCURVESSEPERATE\r\n\t size*=vec3(mix(getCurValueFromGradientFloat(u_SOLSizeGradientX,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientMaxX,normalizedAge),a_Random0.z)\r\n\t ,mix(getCurValueFromGradientFloat(u_SOLSizeGradientY,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientMaxY,normalizedAge),a_Random0.z)\r\n\t\t,mix(getCurValueFromGradientFloat(u_SOLSizeGradientZ,normalizedAge),getCurValueFromGradientFloat(u_SOLSizeGradientMaxZ,normalizedAge),a_Random0.z));\r\n\t#endif\r\n\treturn size;\r\n}\r\n#endif\r\n\r\nfloat computeParticleRotationFloat(in float rotation,in float age,in float normalizedAge)\r\n{ \r\n\t#ifdef ROTATIONOVERLIFETIME\r\n\t\t#ifdef ROTATIONOVERLIFETIMECONSTANT\r\n\t\t\tfloat ageRot=u_ROLAngularVelocityConst*age;\r\n\t rotation+=ageRot;\r\n\t\t#endif\r\n\t\t#ifdef ROTATIONOVERLIFETIMECURVE\r\n\t\t\trotation+=getTotalValueFromGradientFloat(u_ROLAngularVelocityGradient,normalizedAge);\r\n\t\t#endif\r\n\t\t#ifdef ROTATIONOVERLIFETIMERANDOMCONSTANTS\r\n\t\t\tfloat ageRot=mix(u_ROLAngularVelocityConst,u_ROLAngularVelocityConstMax,a_Random0.w)*age;\r\n\t rotation+=ageRot;\r\n\t #endif\r\n\t\t#ifdef ROTATIONOVERLIFETIMERANDOMCURVES\r\n\t\t\trotation+=mix(getTotalValueFromGradientFloat(u_ROLAngularVelocityGradient,normalizedAge),getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientMax,normalizedAge),a_Random0.w);\r\n\t\t#endif\r\n\t#endif\r\n\t#ifdef ROTATIONOVERLIFETIMESEPERATE\r\n\t\t#ifdef ROTATIONOVERLIFETIMECONSTANT\r\n\t\t\tfloat ageRot=u_ROLAngularVelocityConstSeprarate.z*age;\r\n\t rotation+=ageRot;\r\n\t\t#endif\r\n\t\t#ifdef ROTATIONOVERLIFETIMECURVE\r\n\t\t\trotation+=getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientZ,normalizedAge);\r\n\t\t#endif\r\n\t\t#ifdef ROTATIONOVERLIFETIMERANDOMCONSTANTS\r\n\t\t\tfloat ageRot=mix(u_ROLAngularVelocityConstSeprarate.z,u_ROLAngularVelocityConstMaxSeprarate.z,a_Random0.w)*age;\r\n\t rotation+=ageRot;\r\n\t #endif\r\n\t\t#ifdef ROTATIONOVERLIFETIMERANDOMCURVES\r\n\t\t\trotation+=mix(getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientZ,normalizedAge),getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientMaxZ,normalizedAge),a_Random0.w));\r\n\t\t#endif\r\n\t#endif\r\n\treturn rotation;\r\n}\r\n\r\n#if defined(RENDERMODE_MESH)&&(defined(ROTATIONOVERLIFETIME)||defined(ROTATIONOVERLIFETIMESEPERATE))\r\nvec3 computeParticleRotationVec3(in vec3 rotation,in float age,in float normalizedAge)\r\n{ \r\n\t#ifdef ROTATIONOVERLIFETIME\r\n\t#ifdef ROTATIONOVERLIFETIMECONSTANT\r\n\t\t\tfloat ageRot=u_ROLAngularVelocityConst*age;\r\n\t rotation+=ageRot;\r\n\t\t#endif\r\n\t\t#ifdef ROTATIONOVERLIFETIMECURVE\r\n\t\t\trotation+=getTotalValueFromGradientFloat(u_ROLAngularVelocityGradient,normalizedAge);\r\n\t\t#endif\r\n\t\t#ifdef ROTATIONOVERLIFETIMERANDOMCONSTANTS\r\n\t\t\tfloat ageRot=mix(u_ROLAngularVelocityConst,u_ROLAngularVelocityConstMax,a_Random0.w)*age;\r\n\t rotation+=ageRot;\r\n\t #endif\r\n\t\t#ifdef ROTATIONOVERLIFETIMERANDOMCURVES\r\n\t\t\trotation+=mix(getTotalValueFromGradientFloat(u_ROLAngularVelocityGradient,normalizedAge),getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientMax,normalizedAge),a_Random0.w);\r\n\t\t#endif\r\n\t#endif\r\n\t#ifdef ROTATIONOVERLIFETIMESEPERATE\r\n\t\t#ifdef ROTATIONOVERLIFETIMECONSTANT\r\n\t\t\tvec3 ageRot=u_ROLAngularVelocityConstSeprarate*age;\r\n\t rotation+=ageRot;\r\n\t\t#endif\r\n\t\t#ifdef ROTATIONOVERLIFETIMECURVE\r\n\t\t\trotation+=vec3(getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientX,normalizedAge),getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientY,normalizedAge),getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientZ,normalizedAge));\r\n\t\t#endif\r\n\t\t#ifdef ROTATIONOVERLIFETIMERANDOMCONSTANTS\r\n\t\t\tvec3 ageRot=mix(u_ROLAngularVelocityConstSeprarate,u_ROLAngularVelocityConstMaxSeprarate,a_Random0.w)*age;\r\n\t rotation+=ageRot;\r\n\t #endif\r\n\t\t#ifdef ROTATIONOVERLIFETIMERANDOMCURVES\r\n\t\t\trotation+=vec3(mix(getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientX,normalizedAge),getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientMaxX,normalizedAge),a_Random0.w)\r\n\t ,mix(getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientY,normalizedAge),getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientMaxY,normalizedAge),a_Random0.w)\r\n\t ,mix(getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientZ,normalizedAge),getTotalValueFromGradientFloat(u_ROLAngularVelocityGradientMaxZ,normalizedAge),a_Random0.w));\r\n\t\t#endif\r\n\t#endif\r\n\treturn rotation;\r\n}\r\n#endif\r\n\r\nvec2 computeParticleUV(in vec2 uv,in float normalizedAge)\r\n{ \r\n\t#ifdef TEXTURESHEETANIMATIONCURVE\r\n\t\tfloat cycleNormalizedAge=normalizedAge*u_TSACycles;\r\n\t\tfloat frame=getFrameFromGradient(u_TSAGradientUVs,cycleNormalizedAge-floor(cycleNormalizedAge));\r\n\t\tfloat totalULength=frame*u_TSASubUVLength.x;\r\n\t\tfloat floorTotalULength=floor(totalULength);\r\n\t uv.x+=totalULength-floorTotalULength;\r\n\t\tuv.y+=floorTotalULength*u_TSASubUVLength.y;\r\n #endif\r\n\t#ifdef TEXTURESHEETANIMATIONRANDOMCURVE\r\n\t\tfloat cycleNormalizedAge=normalizedAge*u_TSACycles;\r\n\t\tfloat uvNormalizedAge=cycleNormalizedAge-floor(cycleNormalizedAge);\r\n\t float frame=floor(mix(getFrameFromGradient(u_TSAGradientUVs,uvNormalizedAge),getFrameFromGradient(u_TSAMaxGradientUVs,uvNormalizedAge),a_Random1.x));\r\n\t\tfloat totalULength=frame*u_TSASubUVLength.x;\r\n\t\tfloat floorTotalULength=floor(totalULength);\r\n\t uv.x+=totalULength-floorTotalULength;\r\n\t\tuv.y+=floorTotalULength*u_TSASubUVLength.y;\r\n #endif\r\n\treturn uv;\r\n}\r\n\r\nvoid main()\r\n{\r\n\tfloat age = u_CurrentTime - a_DirectionTime.w;\r\n\tfloat normalizedAge = age/a_ShapePositionStartLifeTime.w;\r\n\tvec3 lifeVelocity;\r\n\tif(normalizedAge<1.0)\r\n\t{ \r\n\t\tvec3 startVelocity=a_DirectionTime.xyz*a_StartSpeed;\r\n\t\t#if defined(VELOCITYOVERLIFETIMECONSTANT)||defined(VELOCITYOVERLIFETIMECURVE)||defined(VELOCITYOVERLIFETIMERANDOMCONSTANT)||defined(VELOCITYOVERLIFETIMERANDOMCURVE)\r\n\t\t\tlifeVelocity= computeParticleLifeVelocity(normalizedAge);//计算粒子生命周期速度\r\n\t\t#endif \r\n\t\tvec3 gravityVelocity=u_Gravity*age;\r\n\t\t\r\n\t\tvec4 worldRotation;\r\n\t\tif(u_SimulationSpace==0)\r\n\t\t\tworldRotation=a_SimulationWorldRotation;\r\n\t\telse\r\n\t\t\tworldRotation=u_WorldRotation;\r\n\t\t\r\n\t\tvec3 center=computeParticlePosition(startVelocity, lifeVelocity, age, normalizedAge,gravityVelocity,worldRotation);//计算粒子位置\r\n\t\r\n\t\r\n\t\t#ifdef SPHERHBILLBOARD\r\n\t\t\tvec2 corner=a_CornerTextureCoordinate.xy;//Billboard模式z轴无效\r\n\t\t\tvec3 cameraUpVector =normalize(u_CameraUp);//TODO:是否外面归一化\r\n\t\t\tvec3 sideVector = normalize(cross(u_CameraDirection,cameraUpVector));\r\n\t\t\tvec3 upVector = normalize(cross(sideVector,u_CameraDirection));\r\n\t\t\tcorner*=computeParticleSizeBillbard(a_StartSize.xy,normalizedAge);\r\n\t\t\t#if defined(ROTATIONOVERLIFETIME)||defined(ROTATIONOVERLIFETIMESEPERATE)\r\n\t\t\t\tif(u_ThreeDStartRotation){\r\n\t\t\t\t\tvec3 rotation=vec3(a_StartRotation0.xy,computeParticleRotationFloat(a_StartRotation0.z,age,normalizedAge));\r\n\t\t\t\t\tcenter += u_SizeScale.xzy*rotationByEuler(corner.x*sideVector+corner.y*upVector,rotation);\r\n\t\t\t\t}\r\n\t\t\t\telse{\r\n\t\t\t\t\tfloat rot = computeParticleRotationFloat(a_StartRotation0.x, age,normalizedAge);\r\n\t\t\t\t\tfloat c = cos(rot);\r\n\t\t\t\t\tfloat s = sin(rot);\r\n\t\t\t\t\tmat2 rotation= mat2(c, -s, s, c);\r\n\t\t\t\t\tcorner=rotation*corner;\r\n\t\t\t\t\tcenter += u_SizeScale.xzy*(corner.x*sideVector+corner.y*upVector);\r\n\t\t\t\t}\r\n\t\t\t#else\r\n\t\t\t\tif(u_ThreeDStartRotation){\r\n\t\t\t\t\tcenter += u_SizeScale.xzy*rotationByEuler(corner.x*sideVector+corner.y*upVector,a_StartRotation0);\r\n\t\t\t\t}\r\n\t\t\t\telse{\r\n\t\t\t\t\tfloat c = cos(a_StartRotation0.x);\r\n\t\t\t\t\tfloat s = sin(a_StartRotation0.x);\r\n\t\t\t\t\tmat2 rotation= mat2(c, -s, s, c);\r\n\t\t\t\t\tcorner=rotation*corner;\r\n\t\t\t\t\tcenter += u_SizeScale.xzy*(corner.x*sideVector+corner.y*upVector);\r\n\t\t\t\t}\r\n\t\t\t#endif\r\n\t\t#endif\r\n\t\r\n\t\t#ifdef STRETCHEDBILLBOARD\r\n\t\t\tvec2 corner=a_CornerTextureCoordinate.xy;//Billboard模式z轴无效\r\n\t\t\tvec3 velocity;\r\n\t\t\t#if defined(VELOCITYOVERLIFETIMECONSTANT)||defined(VELOCITYOVERLIFETIMECURVE)||defined(VELOCITYOVERLIFETIMERANDOMCONSTANT)||defined(VELOCITYOVERLIFETIMERANDOMCURVE)\r\n\t\t\t\tif(u_VOLSpaceType==0)\r\n\t\t\t\tvelocity=rotationByQuaternions(u_SizeScale*(startVelocity+lifeVelocity),worldRotation)+gravityVelocity;\r\n\t\t\t\telse\r\n\t\t\t\tvelocity=rotationByQuaternions(u_SizeScale*startVelocity,worldRotation)+lifeVelocity+gravityVelocity;\r\n\t\t\t#else\r\n\t\t\t\tvelocity= rotationByQuaternions(u_SizeScale*startVelocity,worldRotation)+gravityVelocity;\r\n\t\t\t#endif\t\r\n\t\t\tvec3 cameraUpVector = normalize(velocity);\r\n\t\t\tvec3 direction = normalize(center-u_CameraPos);\r\n\t\t\tvec3 sideVector = normalize(cross(direction,normalize(velocity)));\r\n\t\t\t\r\n\t\t\tsideVector=u_SizeScale.xzy*sideVector;\r\n\t\t\tcameraUpVector=length(vec3(u_SizeScale.x,0.0,0.0))*cameraUpVector;\r\n\t\t\t\r\n\t\t\tvec2 size=computeParticleSizeBillbard(a_StartSize.xy,normalizedAge);\r\n\t\t\t\r\n\t\t\tconst mat2 rotaionZHalfPI=mat2(0.0, -1.0, 1.0, 0.0);\r\n\t\t\tcorner=rotaionZHalfPI*corner;\r\n\t\t\tcorner.y=corner.y-abs(corner.y);\r\n\t\t\t\r\n\t\t\tfloat speed=length(velocity);//TODO:\r\n\t\t\tcenter +=sign(u_SizeScale.x)*(sign(u_StretchedBillboardLengthScale)*size.x*corner.x*sideVector+(speed*u_StretchedBillboardSpeedScale+size.y*u_StretchedBillboardLengthScale)*corner.y*cameraUpVector);\r\n\t\t#endif\r\n\t\r\n\t\t#ifdef HORIZONTALBILLBOARD\r\n\t\t\tvec2 corner=a_CornerTextureCoordinate.xy;//Billboard模式z轴无效\r\n\t\t\tconst vec3 cameraUpVector=vec3(0.0,0.0,1.0);\r\n\t\t\tconst vec3 sideVector = vec3(-1.0,0.0,0.0);\r\n\t\t\t\r\n\t\t\tfloat rot = computeParticleRotationFloat(a_StartRotation0.x, age,normalizedAge);\r\n\t\t\tfloat c = cos(rot);\r\n\t\t\tfloat s = sin(rot);\r\n\t\t\tmat2 rotation= mat2(c, -s, s, c);\r\n\t\t\tcorner=rotation*corner*cos(0.78539816339744830961566084581988);//TODO:临时缩小cos45,不确定U3D原因\r\n\t\t\tcorner*=computeParticleSizeBillbard(a_StartSize.xy,normalizedAge);\r\n\t\t\tcenter +=u_SizeScale.xzy*(corner.x*sideVector+ corner.y*cameraUpVector);\r\n\t\t#endif\r\n\t\r\n\t\t#ifdef VERTICALBILLBOARD\r\n\t\t\tvec2 corner=a_CornerTextureCoordinate.xy;//Billboard模式z轴无效\r\n\t\t\tconst vec3 cameraUpVector =vec3(0.0,1.0,0.0);\r\n\t\t\tvec3 sideVector = normalize(cross(u_CameraDirection,cameraUpVector));\r\n\t\t\t\r\n\t\t\tfloat rot = computeParticleRotationFloat(a_StartRotation0.x, age,normalizedAge);\r\n\t\t\tfloat c = cos(rot);\r\n\t\t\tfloat s = sin(rot);\r\n\t\t\tmat2 rotation= mat2(c, -s, s, c);\r\n\t\t\tcorner=rotation*corner*cos(0.78539816339744830961566084581988);//TODO:临时缩小cos45,不确定U3D原因\r\n\t\t\tcorner*=computeParticleSizeBillbard(a_StartSize.xy,normalizedAge);\r\n\t\t\tcenter +=u_SizeScale.xzy*(corner.x*sideVector+ corner.y*cameraUpVector);\r\n\t\t#endif\r\n\t\r\n\t\t#ifdef RENDERMODE_MESH\r\n\t\t\tvec3 size=computeParticleSizeMesh(a_StartSize,normalizedAge);\r\n\t\t\t#if defined(ROTATIONOVERLIFETIME)||defined(ROTATIONOVERLIFETIMESEPERATE)\r\n\t\t\t\tif(u_ThreeDStartRotation){\r\n\t\t\t\t\tvec3 rotation=vec3(a_StartRotation0.xy,computeParticleRotationFloat(a_StartRotation0.z, age,normalizedAge));\r\n\t\t\t\t\tcenter+= rotationByQuaternions(u_SizeScale*rotationByEuler(a_MeshPosition*size,rotation),worldRotation);\r\n\t\t\t\t}\r\n\t\t\t\telse{\r\n\t\t\t\t\t#ifdef ROTATIONOVERLIFETIME\r\n\t\t\t\t\t\tfloat angle=computeParticleRotationFloat(a_StartRotation0.x, age,normalizedAge);\r\n\t\t\t\t\t\tif(a_ShapePositionStartLifeTime.x!=0.0||a_ShapePositionStartLifeTime.y!=0.0){\r\n\t\t\t\t\t\t\tcenter+= (rotationByQuaternions(rotationByAxis(u_SizeScale*a_MeshPosition*size,normalize(cross(vec3(0.0,0.0,1.0),vec3(a_ShapePositionStartLifeTime.xy,0.0))),angle),worldRotation));//已验证\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse{\r\n\t\t\t\t\t\t\t#ifdef SHAPE\r\n\t\t\t\t\t\t\t\tcenter+= u_SizeScale.xzy*(rotationByQuaternions(rotationByAxis(a_MeshPosition*size,vec3(0.0,-1.0,0.0),angle),worldRotation));\r\n\t\t\t\t\t\t\t#else\r\n\t\t\t\t\t\t\t\tif(u_SimulationSpace==0)\r\n\t\t\t\t\t\t\t\t\tcenter+=rotationByAxis(u_SizeScale*a_MeshPosition*size,vec3(0.0,0.0,-1.0),angle);//已验证\r\n\t\t\t\t\t\t\t\telse if(u_SimulationSpace==1)\r\n\t\t\t\t\t\t\t\t\tcenter+=rotationByQuaternions(u_SizeScale*rotationByAxis(a_MeshPosition*size,vec3(0.0,0.0,-1.0),angle),worldRotation);//已验证\r\n\t\t\t\t\t\t\t#endif\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t#endif\r\n\t\t\t\t\t#ifdef ROTATIONOVERLIFETIMESEPERATE\r\n\t\t\t\t\t\t//TODO:是否应合并if(u_ThreeDStartRotation)分支代码,待测试\r\n\t\t\t\t\t\tvec3 angle=computeParticleRotationVec3(vec3(0.0,0.0,-a_StartRotation0.x), age,normalizedAge);\r\n\t\t\t\t\t\tcenter+= (rotationByQuaternions(rotationByEuler(u_SizeScale*a_MeshPosition*size,vec3(angle.x,angle.y,angle.z)),worldRotation));//已验证\r\n\t\t\t\t\t#endif\t\t\r\n\t\t\t\t}\r\n\t\t\t#else\r\n\t\t\t\tif(u_ThreeDStartRotation){\r\n\t\t\t\t\tcenter+= rotationByQuaternions(u_SizeScale*rotationByEuler(a_MeshPosition*size,a_StartRotation0),worldRotation);//已验证\r\n\t\t\t\t}\r\n\t\t\t\telse{\r\n\t\t\t\t\tif(a_ShapePositionStartLifeTime.x!=0.0||a_ShapePositionStartLifeTime.y!=0.0){\r\n\t\t\t\t\t\tif(u_SimulationSpace==0)\r\n\t\t\t\t\t\t\tcenter+= rotationByAxis(u_SizeScale*a_MeshPosition*size,normalize(cross(vec3(0.0,0.0,1.0),vec3(a_ShapePositionStartLifeTime.xy,0.0))),a_StartRotation0.x);\r\n\t\t\t\t\t\telse if(u_SimulationSpace==1)\r\n\t\t\t\t\t\t\tcenter+= (rotationByQuaternions(u_SizeScale*rotationByAxis(a_MeshPosition*size,normalize(cross(vec3(0.0,0.0,1.0),vec3(a_ShapePositionStartLifeTime.xy,0.0))),a_StartRotation0.x),worldRotation));//已验证\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse{\r\n\t\t\t\t\t\t#ifdef SHAPE\r\n\t\t\t\t\t\t\tif(u_SimulationSpace==0)\r\n\t\t\t\t\t\t\t\tcenter+= u_SizeScale*rotationByAxis(a_MeshPosition*size,vec3(0.0,-1.0,0.0),a_StartRotation0.x);\r\n\t\t\t\t\t\t\telse if(u_SimulationSpace==1)\r\n\t\t\t\t\t\t\t\tcenter+= rotationByQuaternions(u_SizeScale*rotationByAxis(a_MeshPosition*size,vec3(0.0,-1.0,0.0),a_StartRotation0.x),worldRotation);\t\r\n\t\t\t\t\t\t#else\r\n\t\t\t\t\t\t\tif(u_SimulationSpace==0)\r\n\t\t\t\t\t\t\t\tcenter+= rotationByAxis(u_SizeScale*a_MeshPosition*size,vec3(0.0,0.0,-1.0),a_StartRotation0.x);\r\n\t\t\t\t\t\t\telse if(u_SimulationSpace==1)\r\n\t\t\t\t\t\t\t\tcenter+= rotationByQuaternions(u_SizeScale*rotationByAxis(a_MeshPosition*size,vec3(0.0,0.0,-1.0),a_StartRotation0.x),worldRotation);//已验证\r\n\t\t\t\t\t\t#endif\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t#endif\r\n\t\t\tv_MeshColor=a_MeshColor;\r\n\t\t#endif\r\n\t\r\n\t\tgl_Position=u_Projection*u_View*vec4(center,1.0);\r\n\t\tv_Color = computeParticleColor(a_StartColor, normalizedAge);\r\n\t\t#ifdef DIFFUSEMAP\r\n\t\t\t#if defined(SPHERHBILLBOARD)||defined(STRETCHEDBILLBOARD)||defined(HORIZONTALBILLBOARD)||defined(VERTICALBILLBOARD)\r\n\t\t\t\tv_TextureCoordinate =computeParticleUV(a_CornerTextureCoordinate.zw, normalizedAge);\r\n\t\t\t#endif\r\n\t\t\t#ifdef RENDERMODE_MESH\r\n\t\t\t\tv_TextureCoordinate =computeParticleUV(a_MeshTextureCoordinate, normalizedAge);\r\n\t\t\t#endif\r\n\t\t\t\r\n\t\t\tv_TextureCoordinate=TransformUV(v_TextureCoordinate,u_TilingOffset);\r\n\t\t#endif\r\n \t}\r\n \telse\r\n\t{\r\n\t\tgl_Position=vec4(2.0,2.0,2.0,1.0);//Discard use out of X(-1,1),Y(-1,1),Z(0,1)\r\n\t}\r\n\tgl_Position=remapGLPositionZ(gl_Position);\r\n}\r\n\r\n";
|
||
|
||
var LayaPBRBRDF = "// allow to explicitly override LAYA_BRDF_GI and LAYA_BRDF_LIGHT in custom shader,default is layaBRDFHighGI and layaBRDFHighLight\r\n#if !defined (LAYA_BRDF_GI) \r\n\t#if defined(LAYA_PBR_BRDF_LOW)\r\n\t\t#define LAYA_BRDF_GI layaBRDFLowGI\r\n\t#elif defined(LAYA_PBR_BRDF_HIGH)\r\n\t\t#define LAYA_BRDF_GI layaBRDFHighGI\r\n\t#endif\r\n#endif\r\n#if !defined (LAYA_BRDF_LIGHT)\r\n\t#if defined(LAYA_PBR_BRDF_LOW)\r\n\t\t#define LAYA_BRDF_LIGHT layaBRDFLowLight\r\n\t#elif defined(LAYA_PBR_BRDF_HIGH)\r\n\t\t#define LAYA_BRDF_LIGHT layaBRDFHighLight\r\n\t#endif\r\n#endif\r\n\r\n#define PI 3.14159265359\r\n#define INV_PI 0.31830988618\r\n\r\nmediump float pow4(mediump float x)\r\n{\r\n\treturn x * x * x * x;\r\n}\r\n\r\nmediump float pow5(mediump float x)\r\n{\r\n\treturn x * x * x * x * x;\r\n}\r\n\r\nmediump vec3 fresnelLerp(mediump vec3 F0,mediump vec3 F90,mediump float cosA)\r\n{\r\n\tfloat t = pow5(1.0 - cosA); // ala Schlick interpoliation\r\n\treturn mix(F0, F90, t);\r\n}\r\n\r\nmediump vec3 fresnelTerm(mediump vec3 F0,mediump float cosA)\r\n{\r\n\tfloat t = pow5(1.0 - cosA); // ala Schlick interpoliation\r\n\treturn F0 + (vec3(1.0) - F0) * t;\r\n}\r\n\r\n// approximage Schlick with ^4 instead of ^5\r\nmediump vec3 fresnelLerpFast (mediump vec3 F0, mediump vec3 F90,mediump float cosA)\r\n{\r\n mediump float t = pow4 (1.0 - cosA);\r\n return mix (F0, F90, t);\r\n}\r\n\r\nfloat smoothnessToPerceptualRoughness(float smoothness)\r\n{\r\n return 1.0 - smoothness;\r\n}\r\n\r\nfloat perceptualRoughnessToRoughness(float perceptualRoughness)\r\n{\r\n return perceptualRoughness * perceptualRoughness;\r\n}\r\n\r\nvec3 safeNormalize(vec3 inVec)\r\n{\r\n\tfloat dp3 = max(0.001,dot(inVec,inVec));\r\n\treturn inVec * inversesqrt(dp3);\r\n}\r\n\r\n// Note: Disney diffuse must be multiply by diffuseAlbedo / PI. This is done outside of this function.\r\nmediump float disneyDiffuse(mediump float NdotV,mediump float NdotL,mediump float LdotH,mediump float perceptualRoughness)\r\n{\r\n\t//https://www.cnblogs.com/herenzhiming/articles/5790389.html\r\n\tmediump float fd90 = 0.5 + 2.0 * LdotH * LdotH * perceptualRoughness;\r\n\t// Two schlick fresnel term\r\n\tmediump float lightScatter = (1.0 + (fd90 - 1.0) * pow5(1.0 - NdotL));\r\n\tmediump float viewScatter = (1.0 + (fd90 - 1.0) * pow5(1.0 - NdotV));\r\n\r\n\treturn lightScatter * viewScatter;\r\n}\r\n\r\n// Ref: http://jcgt.org/published/0003/02/03/paper.pdf\r\nfloat smithJointGGXVisibilityTerm(float NdotL, float NdotV, float roughness)\r\n{\r\n\t// Original formulation:\r\n // lambda_v = (-1 + sqrt(a2 * (1 - NdotL2) / NdotL2 + 1)) * 0.5f;\r\n // lambda_l = (-1 + sqrt(a2 * (1 - NdotV2) / NdotV2 + 1)) * 0.5f;\r\n // G = 1 / (1 + lambda_v + lambda_l);\r\n\r\n\t// scientific code implement:\r\n\t// Reorder code to be more optimal\r\n // half a = roughness;\r\n // half a2 = a * a;\r\n\r\n // half lambdaV = NdotL * sqrt((-NdotV * a2 + NdotV) * NdotV + a2);\r\n // half lambdaL = NdotV * sqrt((-NdotL * a2 + NdotL) * NdotL + a2);\r\n\r\n // Simplify visibility term: (2.0f * NdotL * NdotV) / ((4.0f * NdotL * NdotV) * (lambda_v + lambda_l + 1e-5f));\r\n // return 0.5f / (lambdaV + lambdaL + 1e-5f); \r\n\t// This function is not intended to be running on Mobile,therefore epsilon is smaller than can be represented by half\r\n\r\n\t// Approximation of the above formulation (simplify the sqrt, not mathematically correct but close enough)\r\n\tfloat a = roughness;\r\n\tfloat lambdaV = NdotL * (NdotV * (1.0 - a) + a);\r\n\tfloat lambdaL = NdotV * (NdotL * (1.0 - a) + a);\r\n\treturn 0.5 / (lambdaV + lambdaL + 1e-5);\r\n}\r\n\r\nfloat ggxTerm(float NdotH, float roughness)\r\n{\r\n\tfloat a2 = roughness * roughness;\r\n\tfloat d = (NdotH * a2 - NdotH) * NdotH + 1.0; // 2 mad\r\n\treturn INV_PI * a2 / (d * d + 1e-7); // This function is not intended to be running on Mobile,therefore epsilon is smaller than what can be represented by half//返回值小用half来返回\r\n}\r\n\r\n// BRDF1-------------------------------------------------------------------------------------\r\n\r\n// Note: BRDF entry points use smoothness and oneMinusReflectivity for optimization purposes,\r\n// mostly for DX9 SM2.0 level. Most of the math is being done on these (1-x) values, and that saves a few precious ALU slots.\r\n\r\n// Main Physically Based BRDF\r\n// Derived from Disney work and based on Torrance-Sparrow micro-facet model\r\n//\r\n// BRDF = kD / pi + kS * (D * V * F) / 4\r\n// I = BRDF * NdotL\r\n//\r\n// *NDF GGX:\r\n// *Smith for Visiblity term\r\n// *Schlick approximation for Fresnel\r\nmediump vec4 layaBRDFHighLight(mediump vec3 diffColor, mediump vec3 specColor, mediump float oneMinusReflectivity, float perceptualRoughness,float roughness,mediump float nv,vec3 normal, vec3 viewDir,LayaLight light)\r\n{\r\n\tvec3 halfDir = safeNormalize(viewDir-light.dir);\r\n\r\n\tfloat nl = clamp(dot(normal, -light.dir),0.0,1.0);\r\n\tfloat nh = clamp(dot(normal, halfDir),0.0,1.0);\r\n\tmediump float lv = clamp(dot(light.dir, viewDir),0.0,1.0);\r\n\tmediump float lh = clamp(dot(light.dir, -halfDir),0.0,1.0);\r\n\r\n\t// Diffuse term\r\n\tmediump float diffuseTerm = disneyDiffuse(nv, nl, lh, perceptualRoughness) * nl;\r\n\r\n\t// Specular term\r\n // HACK: theoretically we should divide diffuseTerm by Pi and not multiply specularTerm!\r\n // BUT that will make shader look significantly darker than Legacy ones\r\n\r\n\t// GGX with roughtness to 0 would mean no specular at all, using max(roughness, 0.002) here to match HDrenderloop roughtness remapping.\r\n\troughness = max(roughness, 0.002);\r\n\tfloat V = smithJointGGXVisibilityTerm(nl, nv, roughness);\r\n\tfloat D = ggxTerm(nh, roughness);\r\n\r\n\tfloat specularTerm = V * D * PI; // Torrance-Sparrow model, Fresnel is applied later\r\n\r\n\t//#ifdef LAYA_COLORSPACE_GAMMA\r\n\tspecularTerm = sqrt(max(1e-4, specularTerm));\r\n\t//#endif\r\n\tspecularTerm = max(0.0, specularTerm * nl);\r\n\t\t\r\n\tmediump vec3 color = diffColor * light.color * diffuseTerm + specularTerm * light.color * fresnelTerm(specColor, lh);\r\n\treturn vec4(color, 1.0);\r\n}\r\n\r\nvec4 layaBRDFHighGI(mediump vec3 diffColor,mediump vec3 specColor,mediump float oneMinusReflectivity,float smoothness ,float perceptualRoughness,float roughness,mediump float nv,vec3 normal, vec3 viewDir,LayaGI gi)\r\n{\r\n\t// surfaceReduction = Int D(NdotH) * NdotH * Id(NdotL>0) dH = 1/(roughness^2+1)\r\n\tfloat surfaceReduction;\r\n\tsurfaceReduction = 1.0 - 0.28*roughness*perceptualRoughness;// 1-0.28*x^3 as approximation for (1/(x^4+1))^(1/2.2) on the domain [0;1]\r\n\tfloat grazingTerm = clamp(smoothness + (1.0 - oneMinusReflectivity),0.0,1.0);\r\n\tmediump vec3 color =diffColor * gi.diffuse + surfaceReduction * gi.specular * fresnelLerp(specColor,vec3(grazingTerm), nv);\r\n\treturn vec4(color,1.0);\r\n}\r\n// BRDF1-------------------------------------------------------------------------------------\r\n\r\n\r\n// BRDF2-------------------------------------------------------------------------------------\r\n// Based on Minimalist CookTorrance BRDF\r\n// Implementation is slightly different from original derivation: http://www.thetenthplanet.de/archives/255\r\n//\r\n// *NDF [Modified] GGX:\r\n// *Modified Kelemen and Szirmay-Kalos for Visibility term\r\n// *Fresnel approximated with 1/LdotH\r\nmediump vec4 layaBRDFLowLight (mediump vec3 diffColor, mediump vec3 specColor,mediump float oneMinusReflectivity,float perceptualRoughness,float roughness,mediump float nv,vec3 normal,vec3 viewDir,LayaLight light)\r\n{\r\n vec3 halfDir = safeNormalize (viewDir-light.dir);\r\n mediump float nl = clamp(dot(normal, -light.dir),0.0,1.0);\r\n float nh = clamp(dot(normal, halfDir),0.0,1.0);\r\n float lh = clamp(dot(-light.dir, halfDir),0.0,1.0);\r\n\r\n // GGX Distribution multiplied by combined approximation of Visibility and Fresnel\r\n // See \"Optimizing PBR for Mobile\" from Siggraph 2015 moving mobile graphics course\r\n // https://community.arm.com/events/1155\r\n mediump float a = roughness;\r\n float a2 = a*a;\r\n\r\n float d = nh * nh * (a2 - 1.0) + 1.00001;\r\n\t// #ifdef LAYA_COLORSPACE_GAMMA\r\n\t\t// Tighter approximation for Gamma only rendering mode!\r\n\t\t// DVF = sqrt(DVF);\r\n\t\t// DVF = (a * sqrt(.25)) / (max(sqrt(0.1), lh)*sqrt(roughness + .5) * d);\r\n\t\tfloat specularTerm = a / (max(0.32, lh) * (1.5 + roughness) * d);\r\n\t// #else\r\n\t// \tfloat specularTerm = a2 / (max(0.1f, lh*lh) * (roughness + 0.5f) * (d * d) * 4);\r\n\t// #endif\r\n\r\n // on mobiles (where half actually means something) denominator have risk of overflow\r\n // clamp below was added specifically to \"fix\" that, but dx compiler (we convert bytecode to metal/gles)\r\n // sees that specularTerm have only non-negative terms, so it skips max(0,..) in clamp (leaving only min(100,...))\r\n\r\n\t//#if defined (SHADER_API_MOBILE)\r\n specularTerm = specularTerm - 1e-4;\r\n\t//#endif\r\n\r\n\t// #else\r\n\t\t// // Legacy\r\n\t\t// half specularPower = PerceptualRoughnessToSpecPower(perceptualRoughness);\r\n\t\t// // Modified with approximate Visibility function that takes roughness into account\r\n\t\t// // Original ((n+1)*N.H^n) / (8*Pi * L.H^3) didn't take into account roughness\r\n\t\t// // and produced extremely bright specular at grazing angles\r\n\r\n\t\t// half invV = lh * lh * smoothness + perceptualRoughness * perceptualRoughness; // approx ModifiedKelemenVisibilityTerm(lh, perceptualRoughness);\r\n\t\t// half invF = lh;\r\n\r\n\t\t// half specularTerm = ((specularPower + 1) * pow (nh, specularPower)) / (8 * invV * invF + 1e-4h);\r\n\r\n\t\t// #ifdef LAYA_COLORSPACE_GAMMA\r\n\t\t// \tspecularTerm = sqrt(max(1e-4f, specularTerm));\r\n\t\t// #endif\r\n\t// #endif\r\n\r\n\t// #if defined (SHADER_API_MOBILE)\r\n\t\tspecularTerm = clamp(specularTerm, 0.0, 100.0); // Prevent FP16 overflow on mobiles\r\n\t// #endif\r\n \r\n mediump vec3 color = (diffColor + specularTerm * specColor) * light.color * nl;\r\n\r\n return vec4(color, 1.0);\r\n}\r\n\r\nmediump vec4 layaBRDFLowGI (mediump vec3 diffColor, mediump vec3 specColor,mediump float oneMinusReflectivity,mediump float smoothness,float perceptualRoughness,float roughness,mediump float nv,vec3 normal,vec3 viewDir,LayaGI gi)\r\n{\r\n\t// surfaceReduction = Int D(NdotH) * NdotH * Id(NdotL>0) dH = 1/(realRoughness^2+1)\r\n\r\n // 1-0.28*x^3 as approximation for (1/(x^4+1))^(1/2.2) on the domain [0;1]\r\n // 1-x^3*(0.6-0.08*x) approximation for 1/(x^4+1)\r\n\t// #ifdef LAYA_COLORSPACE_GAMMA\r\n\t\tmediump float surfaceReduction = 0.28;\r\n\t// #else\r\n\t\t// mediump float surfaceReduction = (0.6-0.08*perceptualRoughness);\r\n\t// #endif\r\n\r\n surfaceReduction = 1.0 - roughness*perceptualRoughness*surfaceReduction;\r\n\r\n\tmediump float grazingTerm = clamp(smoothness + (1.0-oneMinusReflectivity),0.0,1.0);\r\n\tmediump vec3 color =gi.diffuse * diffColor+ surfaceReduction * gi.specular * fresnelLerpFast (specColor, vec3(grazingTerm), nv);\r\n\r\n return vec4(color, 1.0);\r\n}\r\n// BRDF2-------------------------------------------------------------------------------------";
|
||
|
||
var PBRCore = "struct FragmentCommonData{\r\n\tvec3 diffColor;\r\n\tvec3 specColor;\r\n\tfloat oneMinusReflectivity;\r\n\tfloat smoothness;\r\n\t//vec3 eyeVec;TODO:maybe can remove\r\n\t//float alpha;\r\n\t//vec3 reflUVW;\r\n};\r\n\r\n#if !defined(SETUP_BRDF_INPUT)//shader内部的宏需要将改成#ifdef改成#if类型 不然会被Laya的shader分析器优化掉\r\n #define SETUP_BRDF_INPUT metallicSetup//default is metallicSetup,also can be other. \r\n#endif\r\n\r\nconst mediump vec4 dielectricSpecularColor = vec4(0.220916301, 0.220916301, 0.220916301, 1.0 - 0.220916301);\r\n\r\nmediump vec3 diffuseAndSpecularFromMetallic(mediump vec3 albedo,mediump float metallic, out mediump vec3 specColor, out mediump float oneMinusReflectivity)\r\n{\r\n\tspecColor = mix(dielectricSpecularColor.rgb, albedo, metallic);\r\n\toneMinusReflectivity= dielectricSpecularColor.a*(1.0-metallic);//diffuse proportion\r\n\treturn albedo * oneMinusReflectivity;\r\n}\r\n\r\nmediump float specularStrength(mediump vec3 specular)\r\n{\r\n return max (max (specular.r, specular.g), specular.b);\r\n}\r\n\r\n// Diffuse/Spec Energy conservation\r\nmediump vec3 energyConservationBetweenDiffuseAndSpecular (mediump vec3 albedo, mediump vec3 specColor, out mediump float oneMinusReflectivity)\r\n{\r\n\toneMinusReflectivity = 1.0 - specularStrength(specColor);\r\n return albedo * (vec3(1.0) - specColor);\r\n}\r\n\r\n#ifdef TRANSPARENTBLEND\r\n\tmediump vec3 preMultiplyAlpha (mediump vec3 diffColor, mediump float alpha, mediump float oneMinusReflectivity,out mediump float modifiedAlpha)\r\n\t{\r\n\t\t// Transparency 'removes' from Diffuse component\r\n\t\tdiffColor *= alpha;\r\n\t\t// Reflectivity 'removes' from the rest of components, including Transparency\r\n\t\t// modifiedAlpha = 1.0-(1.0-alpha)*(1.0-reflectivity) = 1.0-(oneMinusReflectivity - alpha*oneMinusReflectivity) = 1.0-oneMinusReflectivity + alpha*oneMinusReflectivity\r\n\t\tmodifiedAlpha = 1.0 - oneMinusReflectivity + alpha*oneMinusReflectivity;\r\n\t\treturn diffColor;\r\n\t}\r\n#endif\r\n\r\nFragmentCommonData metallicSetup(vec2 uv)\r\n{\r\n\tmediump vec2 metallicGloss = getMetallicGloss(uv);\r\n\tmediump float metallic = metallicGloss.x;\r\n\tmediump float smoothness = metallicGloss.y; // this is 1 minus the square root of real roughness m.\r\n\tmediump float oneMinusReflectivity;\r\n\tmediump vec3 specColor;\r\n\tmediump vec3 diffColor = diffuseAndSpecularFromMetallic(albedo(uv), metallic,/*out*/specColor,/*out*/oneMinusReflectivity);\r\n\r\n\tFragmentCommonData o;\r\n\to.diffColor = diffColor;\r\n\to.specColor = specColor;\r\n\to.oneMinusReflectivity = oneMinusReflectivity;\r\n\to.smoothness = smoothness;\r\n\treturn o;\r\n}\r\n\r\nFragmentCommonData specularSetup(vec2 uv)\r\n{\r\n mediump vec4 specGloss = specularGloss(uv);\r\n mediump vec3 specColor = specGloss.rgb;\r\n mediump float smoothness = specGloss.a;\r\n\r\n mediump float oneMinusReflectivity;\r\n mediump vec3 diffColor = energyConservationBetweenDiffuseAndSpecular (albedo(uv), specColor, /*out*/ oneMinusReflectivity);\r\n\r\n FragmentCommonData o;\r\n o.diffColor = diffColor;\r\n o.specColor = specColor;\r\n o.oneMinusReflectivity = oneMinusReflectivity;\r\n o.smoothness = smoothness;\r\n return o;\r\n}\r\n\r\nLayaGI fragmentGI(float smoothness,vec3 eyeVec,mediump float occlusion,mediump vec2 lightmapUV,vec3 worldnormal,vec3 worldPos)\r\n{\r\n\tLayaGIInput giInput;\r\n\t#ifdef LIGHTMAP\r\n\t\tgiInput.lightmapUV=lightmapUV;\r\n\t#endif\r\n\tgiInput.worldPos = worldPos;\r\n\r\n\tvec3 worldViewDir = -eyeVec;\r\n\tmediump vec4 uvwRoughness;\r\n\tuvwRoughness.rgb = reflect(worldViewDir, worldnormal);//reflectUVW\r\n\tuvwRoughness.a= smoothnessToPerceptualRoughness(smoothness);//perceptualRoughness\r\n\r\n\treturn layaGlobalIllumination(giInput,occlusion, worldnormal, uvwRoughness);\r\n}\r\n\r\n\r\nvec3 perPixelWorldNormal(vec2 uv,vec3 normal,vec3 binormal,vec3 tangent)\r\n{\r\n\t#ifdef NORMALTEXTURE\r\n\t\tmediump vec3 normalTangent=normalInTangentSpace(uv);\r\n\t\tvec3 normalWorld = normalize(tangent * normalTangent.x + binormal * normalTangent.y + normal * normalTangent.z);\r\n\t#else\r\n\t\tvec3 normalWorld = normalize(normal);\r\n\t#endif\r\n\t\treturn normalWorld;\r\n}\r\n\r\nvoid fragmentForward()\r\n{\r\n\tvec2 uv;\r\n\t#if defined(ALBEDOTEXTURE)||defined(METALLICGLOSSTEXTURE)||defined(NORMALTEXTURE)||defined(EMISSIONTEXTURE)||defined(OCCLUSIONTEXTURE)||defined(PARALLAXTEXTURE)\r\n\t\t#ifdef PARALLAXTEXTURE\r\n\t\t\tuv = parallax(v_Texcoord0,normalize(v_ViewDirForParallax));\r\n\t\t#else\r\n\t\t\tuv = v_Texcoord0;\r\n\t\t#endif\r\n\t#endif\r\n\r\n\tmediump float alpha = getAlpha(uv);\r\n\t#ifdef ALPHATEST\r\n\t\tif(alpha<u_AlphaTestValue)\r\n\t\t\tdiscard;\r\n\t#endif\r\n\r\n\tFragmentCommonData o = SETUP_BRDF_INPUT(uv);\r\n\t\r\n\tvec3 binormal;\r\n\tvec3 tangent;\r\n\t#ifdef NORMALTEXTURE\r\n\t\ttangent = v_Tangent;\r\n\t\tbinormal = v_Binormal;\r\n\t#endif\r\n\r\n\tvec3 normal = v_Normal;\r\n\tvec3 normalWorld = perPixelWorldNormal(uv,normal,binormal,tangent);//In FS if the normal use mediump before normalize will cause precision prolem in mobile device.\r\n\tvec3 eyeVec = normalize(v_EyeVec);\r\n\tvec3 posworld = v_PositionWorld;\r\n\r\n\t#ifdef TRANSPARENTBLEND\r\n\t\to.diffColor=preMultiplyAlpha(o.diffColor,alpha,o.oneMinusReflectivity,/*out*/alpha);// shader relies on pre-multiply alpha-blend (srcBlend = One, dstBlend = OneMinusSrcAlpha)\r\n\t#endif\r\n\r\n\tmediump float occlusion = getOcclusion(uv);\r\n\tmediump vec2 lightMapUV;\r\n\t#ifdef LIGHTMAP\r\n\t\tlightMapUV=v_LightMapUV;\r\n\t#endif\r\n\tfloat perceptualRoughness = smoothnessToPerceptualRoughness(o.smoothness);\r\n\tfloat roughness = perceptualRoughnessToRoughness(perceptualRoughness);\r\n\tfloat nv = abs(dot(normalWorld, eyeVec));\r\n\tLayaGI gi =fragmentGI(o.smoothness,eyeVec,occlusion,lightMapUV,normalWorld,posworld);\r\n\tvec4 color = LAYA_BRDF_GI(o.diffColor,o.specColor,o.oneMinusReflectivity,o.smoothness,perceptualRoughness,roughness,nv,normalWorld,eyeVec,gi);\r\n\t\r\n\tfloat shadowAttenuation = 1.0;\r\n\t#ifdef LEGACYSINGLELIGHTING\r\n\t\t#ifdef DIRECTIONLIGHT\r\n\t\t\t#if defined(CALCULATE_SHADOWS)//shader中自定义的宏不可用ifdef 必须改成if defined\r\n\t\t\t\t#ifdef SHADOW_CASCADE\r\n\t\t\t\t\tvec4 shadowCoord = getShadowCoord(vec4(v_PositionWorld,1.0));\r\n\t\t\t\t#else\r\n\t\t\t\t\tvec4 shadowCoord = v_ShadowCoord;\r\n\t\t\t\t#endif\r\n\t\t\t\tshadowAttenuation=sampleShadowmap(shadowCoord);\r\n\t\t\t#endif\r\n\t\t\tLayaLight dirLight = layaDirectionLightToLight(u_DirectionLight,shadowAttenuation);\r\n\t\t\tcolor+= LAYA_BRDF_LIGHT(o.diffColor,o.specColor,o.oneMinusReflectivity,perceptualRoughness,roughness,nv,normalWorld,eyeVec,dirLight);\r\n\t\t#endif\r\n\t\r\n\t\t#ifdef POINTLIGHT\r\n\t\t\tshadowAttenuation = 1.0;\r\n\t\t\tLayaLight poiLight = layaPointLightToLight(posworld,normalWorld,u_PointLight,shadowAttenuation);\r\n\t\t\tcolor+= LAYA_BRDF_LIGHT(o.diffColor,o.specColor,o.oneMinusReflectivity,perceptualRoughness,roughness,nv,normalWorld,eyeVec,poiLight);\r\n\t\t#endif\r\n\t\t\r\n\t\t#ifdef SPOTLIGHT\r\n\t\t\tshadowAttenuation = 1.0;\r\n\t\t\t#if defined(CALCULATE_SPOTSHADOWS)//shader中自定义的宏不可用ifdef 必须改成if defined\r\n\t\t\t\tvec4 spotShadowcoord = v_SpotShadowCoord;\r\n\t\t\t\tshadowAttenuation = sampleSpotShadowmap(spotShadowcoord);\r\n\t\t\t#endif\r\n\t\t LayaLight spoLight = layaSpotLightToLight(posworld,normalWorld,u_SpotLight,shadowAttenuation);\r\n\t\t\tcolor+= LAYA_BRDF_LIGHT(o.diffColor,o.specColor,o.oneMinusReflectivity,perceptualRoughness,roughness,nv,normalWorld,eyeVec,spoLight);\r\n\t\t#endif\r\n\t#else\r\n\t \t#ifdef DIRECTIONLIGHT\r\n\t\t\tfor (int i = 0; i < MAX_LIGHT_COUNT; i++) \r\n\t\t\t{\r\n\t\t\t\tshadowAttenuation = 1.0;\r\n\t\t\t\tif(i >= u_DirationLightCount)\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t#if defined(CALCULATE_SHADOWS)//shader中自定义的宏不可用ifdef 必须改成if defined\r\n\t\t\t\t\tif(i == 0)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t#ifdef SHADOW_CASCADE\r\n\t\t\t\t\t\t\tvec4 shadowCoord = getShadowCoord(vec4(v_PositionWorld,1.0));\r\n\t\t\t\t\t\t#else\r\n\t\t\t\t\t\t\tvec4 shadowCoord = v_ShadowCoord;\r\n\t\t\t\t\t\t#endif\r\n\t\t\t\t\t\tshadowAttenuation *= sampleShadowmap(shadowCoord);\r\n\t\t\t\t\t}\r\n\t\t\t\t#endif\r\n\t\t\t\tDirectionLight directionLight = getDirectionLight(u_LightBuffer,i);\r\n\t\t\t\tLayaLight dirLight = layaDirectionLightToLight(directionLight,shadowAttenuation);\r\n\t\t\t \tcolor+=LAYA_BRDF_LIGHT(o.diffColor,o.specColor,o.oneMinusReflectivity,perceptualRoughness,roughness,nv,normalWorld,eyeVec,dirLight);\r\n\t\t\t}\r\n\t \t#endif\r\n\t\t#if defined(POINTLIGHT)||defined(SPOTLIGHT)\r\n\t\t\tivec4 clusterInfo =getClusterInfo(u_LightClusterBuffer,u_View,u_Viewport, v_PositionWorld,gl_FragCoord,u_ProjectionParams);\r\n\t\t\t#ifdef POINTLIGHT\r\n\t\t\t\tfor (int i = 0; i < MAX_LIGHT_COUNT; i++) \r\n\t\t\t\t{\r\n\t\t\t\t\tshadowAttenuation = 1.0;\r\n\t\t\t\t\tif(i >= clusterInfo.x)//PointLightCount\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tPointLight pointLight = getPointLight(u_LightBuffer,u_LightClusterBuffer,clusterInfo,i);\r\n\t\t\t\t\tLayaLight poiLight = layaPointLightToLight(posworld,normalWorld,pointLight,shadowAttenuation);\r\n\t\t\t\t\tcolor+= LAYA_BRDF_LIGHT(o.diffColor,o.specColor,o.oneMinusReflectivity,perceptualRoughness,roughness,nv,normalWorld,eyeVec,poiLight);\r\n\t\t\t\t}\r\n\t\t\t#endif\r\n\t\t\t#ifdef SPOTLIGHT\r\n\t\t\t\tfor (int i = 0; i < MAX_LIGHT_COUNT; i++) \r\n\t\t\t\t{\r\n\t\t\t\t\tshadowAttenuation = 1.0;\r\n\t\t\t\t\tif(i >= clusterInfo.y)//SpotLightCount\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t#if defined(CALCULATE_SPOTSHADOWS)//shader中自定义的宏不可用ifdef 必须改成if defined\r\n\t\t\t\t\t\tif(i == 0)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tvec4 spotShadowcoord = v_SpotShadowCoord;\r\n\t\t\t\t\t\t\tshadowAttenuation= sampleSpotShadowmap(spotShadowcoord);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t#endif\r\n\t\t\t\t\tSpotLight spotLight = getSpotLight(u_LightBuffer,u_LightClusterBuffer,clusterInfo,i);\r\n\t\t\t\t\tLayaLight spoLight = layaSpotLightToLight(posworld,normalWorld,spotLight,shadowAttenuation);\r\n\t\t\t\t\tcolor+= LAYA_BRDF_LIGHT(o.diffColor,o.specColor,o.oneMinusReflectivity,perceptualRoughness,roughness,nv,normalWorld,eyeVec,spoLight);\r\n\t\t\t\t}\r\n\t\t\t#endif\r\n\t\t#endif\r\n\t #endif\r\n\r\n\t#ifdef EMISSION\r\n\t\tcolor.rgb += emission(uv);\r\n\t#endif\r\n\r\n\t#ifdef FOG\r\n\t\tfloat lerpFact=clamp((1.0/gl_FragCoord.w-u_FogStart)/u_FogRange,0.0,1.0);\r\n\t\tcolor.rgb=mix(color.rgb,u_FogColor,lerpFact);\r\n\t#endif\r\n\t\r\n\tgl_FragColor=vec4(color.rgb,alpha);\r\n}\r\n\r\n\r\n\r\n";
|
||
|
||
var PBRVSInput = "attribute vec4 a_Position;\r\n\r\n#ifdef GPU_INSTANCE\r\n\tuniform mat4 u_ViewProjection;\r\n\tattribute mat4 a_WorldMat;\r\n#else\r\n\tuniform mat4 u_MvpMatrix;\r\n\tuniform mat4 u_WorldMat;\r\n#endif\r\n\r\n#ifdef BONE\r\n\tconst int c_MaxBoneCount = 24;\r\n\tattribute vec4 a_BoneIndices;\r\n\tattribute vec4 a_BoneWeights;\r\n\tuniform mat4 u_Bones[c_MaxBoneCount];\r\n#endif\r\n\r\nattribute vec3 a_Normal;\r\nvarying vec3 v_Normal; \r\n\r\n#if defined(NORMALTEXTURE)||defined(PARALLAXTEXTURE)\r\n\tattribute vec4 a_Tangent0;\r\n\tvarying vec3 v_Tangent;\r\n\tvarying vec3 v_Binormal;\r\n #ifdef PARALLAXTEXTURE\r\n\t varying vec3 v_ViewDirForParallax;\r\n #endif\r\n#endif\r\n\r\n#if defined(ALBEDOTEXTURE)||defined(METALLICGLOSSTEXTURE)||defined(NORMALTEXTURE)||defined(EMISSIONTEXTURE)||defined(OCCLUSIONTEXTURE)||defined(PARALLAXTEXTURE)||(defined(LIGHTMAP)&&defined(UV))\r\n\tattribute vec2 a_Texcoord0;\r\n\tvarying vec2 v_Texcoord0;\r\n#endif\r\n\r\n#if defined(LIGHTMAP)&&defined(UV1)\r\n\tattribute vec2 a_Texcoord1;\r\n#endif\r\n\r\n#ifdef LIGHTMAP\r\n\tuniform vec4 u_LightmapScaleOffset;\r\n\tvarying vec2 v_LightMapUV;\r\n#endif\r\n\r\nuniform vec3 u_CameraPos;\r\nvarying vec3 v_EyeVec;\r\nvarying vec3 v_PositionWorld;\r\nvarying float v_posViewZ;\r\n\r\n#if defined(CALCULATE_SHADOWS)&&!defined(SHADOW_CASCADE)\r\n\tvarying vec4 v_ShadowCoord;\r\n#endif\r\n\r\n#if defined(CALCULATE_SPOTSHADOWS)//shader中自定义的宏不可用ifdef 必须改成if defined\r\n\tvarying vec4 v_SpotShadowCoord;\r\n#endif\r\n\r\nuniform vec4 u_TilingOffset;\r\n";
|
||
|
||
var PBRFSInput = "#ifdef ALPHATEST\r\n\tuniform float u_AlphaTestValue;\r\n#endif\r\n\r\nuniform vec4 u_AlbedoColor;\r\n\r\n#ifdef NORMALTEXTURE\r\n\tuniform sampler2D u_NormalTexture;\r\n\tuniform float u_NormalScale;\r\n#endif\r\n\r\n#ifdef ALBEDOTEXTURE\r\n\tuniform sampler2D u_AlbedoTexture;\r\n#endif\r\n\r\n#ifdef METALLICGLOSSTEXTURE\r\n\tuniform sampler2D u_MetallicGlossTexture;\r\n#endif\r\nuniform float u_Metallic;\r\n\r\n#ifdef SPECULARGLOSSTEXTURE\r\n\tuniform sampler2D u_SpecGlossTexture;\r\n#endif\r\nuniform vec3 u_SpecularColor;\r\n\r\nuniform float u_Smoothness;\r\nuniform float u_SmoothnessScale;\r\n\r\n#ifdef PARALLAXTEXTURE\r\n\tuniform sampler2D u_ParallaxTexture;\r\n\tuniform float u_ParallaxScale;\r\n\tvarying vec3 v_ViewDirForParallax;\r\n#endif\r\n\r\n#ifdef OCCLUSIONTEXTURE\r\n\tuniform sampler2D u_OcclusionTexture;\r\n\tuniform float u_occlusionStrength;\r\n#endif\r\n\r\n#ifdef EMISSION \r\n\t#ifdef EMISSIONTEXTURE\r\n\t\tuniform sampler2D u_EmissionTexture;\r\n\t#endif\r\n\tuniform vec4 u_EmissionColor;\r\n#endif\r\n\r\n#if defined(ALBEDOTEXTURE)||defined(METALLICGLOSSTEXTURE)||defined(NORMALTEXTURE)||defined(EMISSIONTEXTURE)||defined(OCCLUSIONTEXTURE)||defined(PARALLAXTEXTURE)\r\n\tvarying vec2 v_Texcoord0;\r\n#endif\r\n\r\n#ifdef LIGHTMAP\r\n\tvarying vec2 v_LightMapUV;\r\n\tuniform sampler2D u_LightMap;\r\n\t#ifdef LIGHTMAP_DIRECTIONAL\r\n\t\tuniform sampler2D u_LightMapDirection;\r\n\t#endif\r\n#endif\r\n\r\nvarying vec3 v_Normal; \r\n\r\n#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)\r\n\t#ifdef LEGACYSINGLELIGHTING\r\n\t\t#ifdef DIRECTIONLIGHT\r\n\t\t\tuniform DirectionLight u_DirectionLight;\r\n\t\t#endif\r\n\t\t#ifdef POINTLIGHT\r\n\t\t\tuniform PointLight u_PointLight;\r\n\t\t#endif\r\n\t\t#ifdef SPOTLIGHT\r\n\t\t\tuniform SpotLight u_SpotLight;\r\n\t\t#endif\r\n\t#else\r\n\t\tuniform mat4 u_View;\r\n\t\tuniform vec4 u_ProjectionParams;\r\n\t\tuniform vec4 u_Viewport;\r\n\t\tuniform int u_DirationLightCount;\r\n\t\tuniform sampler2D u_LightBuffer;\r\n\t\tuniform sampler2D u_LightClusterBuffer;\r\n\t#endif\r\n#endif\r\n\r\nvarying vec3 v_EyeVec;\r\n\r\n#ifdef NORMALTEXTURE\r\n\tvarying vec3 v_Tangent;\r\n\tvarying vec3 v_Binormal;\r\n#endif\r\n\r\n#ifdef FOG\r\n\tuniform float u_FogStart;\r\n\tuniform float u_FogRange;\r\n\tuniform vec3 u_FogColor;\r\n#endif\r\n\r\n\r\n//后面考虑宏TODO\r\nvarying vec3 v_PositionWorld;\r\n\r\n#if defined(CALCULATE_SHADOWS)&&!defined(SHADOW_CASCADE)\r\n\tvarying vec4 v_ShadowCoord;\r\n#endif\r\n\r\n#if defined(CALCULATE_SPOTSHADOWS)//shader中自定义的宏不可用ifdef 必须改成if defined\r\n\tvarying vec4 v_SpotShadowCoord;\r\n#endif\r\n\r\nmediump float lerpOneTo(mediump float b, mediump float t)\r\n{\r\n mediump float oneMinusT = 1.0 - t;\r\n return oneMinusT + b * t;\r\n}\r\n\r\n#ifdef EMISSION \r\n\tvec3 emission(vec2 uv)\r\n\t{\r\n\t\t#ifdef EMISSIONTEXTURE\r\n\t\t\treturn texture2D(u_EmissionTexture, uv).rgb * u_EmissionColor.rgb;\r\n\t\t#else\r\n\t\t\treturn u_EmissionColor.rgb;\r\n\t\t#endif\r\n\t}\r\n#endif\r\n\r\nmediump float getAlpha(vec2 uv)\r\n{\r\n\t#ifdef SMOOTHNESSSOURCE_ALBEDOTEXTURE_ALPHA\r\n\t\treturn u_AlbedoColor.a;\r\n\t#else\r\n\t\t#ifdef ALBEDOTEXTURE\r\n\t\t\treturn texture2D(u_AlbedoTexture, uv).a * u_AlbedoColor.a;\r\n\t\t#else\r\n\t\t\treturn u_AlbedoColor.a;\r\n\t\t#endif\r\n\t#endif\r\n}\r\n\r\nmediump float getOcclusion(vec2 uv)\r\n{\r\n\t#ifdef OCCLUSIONTEXTURE\r\n\t\tmediump float occ = texture2D(u_OcclusionTexture, uv).g;\r\n\t\treturn lerpOneTo(occ, u_occlusionStrength);\r\n\t#else\r\n\t\treturn 1.0;\r\n\t#endif\r\n}\r\n\r\nmediump vec3 albedo(vec2 uv)\r\n{\r\n\t#ifdef ALBEDOTEXTURE\r\n\t\treturn u_AlbedoColor.rgb * texture2D(u_AlbedoTexture, uv).rgb;\r\n\t#else\r\n\t\treturn u_AlbedoColor.rgb;\r\n\t#endif\r\n\t//TODO:Detail Texture\r\n}\r\n\r\nmediump vec2 getMetallicGloss(vec2 uv)\r\n{\r\n\tmediump vec2 ms;//x is metallic,y is smoothness\r\n\t#ifdef METALLICGLOSSTEXTURE\r\n\t\t#ifdef SMOOTHNESSSOURCE_ALBEDOTEXTURE_ALPHA\r\n\t\t\tms.x = texture2D(u_MetallicGlossTexture, uv).r;\r\n\t\t\t#ifdef ALBEDOTEXTURE\r\n\t\t\t\tms.y = texture2D(u_AlbedoTexture, uv).a*u_SmoothnessScale;\r\n\t\t\t#else\r\n\t\t\t\tms.y = u_SmoothnessScale;\r\n\t\t\t#endif\r\n\t\t#else\r\n\t\t\tms = texture2D(u_MetallicGlossTexture, uv).ra;\r\n\t\t\tms.y *= u_SmoothnessScale;\r\n\t\t#endif\r\n\t#else\r\n\t\tms.x = u_Metallic;\r\n\t\t#ifdef SMOOTHNESSSOURCE_ALBEDOTEXTURE_ALPHA\r\n\t\t\t#ifdef ALBEDOTEXTURE\r\n\t\t\t\tms.y = texture2D(u_AlbedoTexture, uv).a * u_SmoothnessScale;\r\n\t\t\t#else\r\n\t\t\t\tms.y = u_SmoothnessScale;\r\n\t\t\t#endif\r\n\t\t#else\r\n\t\t\tms.y = u_Smoothness;\r\n\t\t#endif\r\n\t#endif\r\n\treturn ms;\r\n}\r\n\r\nmediump vec4 specularGloss(vec2 uv)\r\n{\r\n\tmediump vec4 sg;\r\n\t#ifdef SPECULARGLOSSTEXTURE\r\n\t\t#ifdef SMOOTHNESSSOURCE_ALBEDOTEXTURE_ALPHA\r\n\t\t\tsg.rgb = texture2D(u_SpecGlossTexture, uv).rgb;\r\n\t\t\t#ifdef ALBEDOTEXTURE\r\n\t\t\t\tsg.a = texture2D(u_AlbedoTexture, uv).a*u_SmoothnessScale;\r\n\t\t\t#else\r\n\t\t\t\tsg.a = u_SmoothnessScale;\r\n\t\t\t#endif\r\n\t\t#else\r\n\t\t\tsg = texture2D(u_SpecGlossTexture, uv);\r\n\t\t\tsg.a *= u_SmoothnessScale;\r\n\t\t#endif\r\n\t#else\r\n\t\tsg.rgb = u_SpecularColor.rgb;\r\n\t\t#ifdef SMOOTHNESSSOURCE_ALBEDOTEXTURE_ALPHA\r\n\t\t\t#ifdef ALBEDOTEXTURE\r\n\t\t\t\tsg.a = texture2D(u_AlbedoTexture, uv).a * u_SmoothnessScale;\r\n\t\t\t#else\r\n\t\t\t\tsg.a = u_SmoothnessScale;\r\n\t\t\t#endif\r\n\t\t#else\r\n\t\t\tsg.a = u_Smoothness;\r\n\t\t#endif\r\n\t#endif\r\n\t\treturn sg;\r\n}\r\n\r\n\r\n#ifdef NORMALTEXTURE\r\n\tmediump vec3 unpackScaleNormal(mediump vec3 packednormal, mediump float bumpScale)\r\n\t{\r\n\t\tmediump vec3 normal = packednormal.xyz * 2.0 - 1.0;\r\n\t\tnormal.y=-normal.y;//NOTE:because unity to LayaAir coordSystem.\r\n\t\tnormal.xy *= bumpScale;\r\n\t\treturn normal;\r\n\t}\r\n\t\r\n\tmediump vec3 normalInTangentSpace(vec2 texcoords)\r\n\t{\r\n\t\tmediump vec3 normalTangent = unpackScaleNormal(texture2D(u_NormalTexture, texcoords).rgb,u_NormalScale);\r\n\t\treturn normalTangent;\r\n\t}\r\n#endif\r\n\r\n#ifdef PARALLAXTEXTURE\r\n\tmediump vec2 parallaxOffset1Step(mediump float h, mediump float height, mediump vec3 viewDir)\r\n\t{\r\n\t\th = h * height - height / 2.0;\r\n\t\tviewDir.z += 0.42;\r\n\t\treturn h * (viewDir.xy / viewDir.z);\r\n\t}\r\n\r\n\tvec2 parallax(vec2 texcoords, mediump vec3 viewDir)\r\n\t{\r\n\t\tmediump float h = texture2D(u_ParallaxTexture, texcoords.xy).g;\r\n\t\tvec2 offset = parallaxOffset1Step(h, u_ParallaxScale, viewDir);\r\n\t\treturn texcoords+offset;\r\n\t}\r\n#endif\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n";
|
||
|
||
var PBRVertex = "vec2 transformLightMapUV(in vec2 texcoord,in vec4 lightmapScaleOffset)\r\n{\r\n\tvec2 lightMapUV=vec2(texcoord.x,1.0-texcoord.y)*lightmapScaleOffset.xy+lightmapScaleOffset.zw;\r\n\tlightMapUV.y=1.0-lightMapUV.y;\r\n\treturn lightMapUV; \r\n}\r\n\r\nvoid vertexForward()\r\n{\r\n\tvec4 position;\r\n\t#ifdef BONE\r\n\t\tmat4 skinTransform;\r\n\t \t#ifdef SIMPLEBONE\r\n\t\t\tfloat currentPixelPos;\r\n\t\t\t#ifdef GPU_INSTANCE\r\n\t\t\t\tcurrentPixelPos = a_SimpleTextureParams.x+a_SimpleTextureParams.y;\r\n\t\t\t#else\r\n\t\t\t\tcurrentPixelPos = u_SimpleAnimatorParams.x+u_SimpleAnimatorParams.y;\r\n\t\t\t#endif\r\n\t\t\tfloat offset = 1.0/u_SimpleAnimatorTextureSize;\r\n\t\t\tskinTransform = loadMatFromTexture(currentPixelPos,int(a_BoneIndices.x),offset) * a_BoneWeights.x;\r\n\t\t\tskinTransform += loadMatFromTexture(currentPixelPos,int(a_BoneIndices.y),offset) * a_BoneWeights.y;\r\n\t\t\tskinTransform += loadMatFromTexture(currentPixelPos,int(a_BoneIndices.z),offset) * a_BoneWeights.z;\r\n\t\t\tskinTransform += loadMatFromTexture(currentPixelPos,int(a_BoneIndices.w),offset) * a_BoneWeights.w;\r\n\t\t#else\r\n\t\t\tskinTransform = u_Bones[int(a_BoneIndices.x)] * a_BoneWeights.x;\r\n\t\t\tskinTransform += u_Bones[int(a_BoneIndices.y)] * a_BoneWeights.y;\r\n\t\t\tskinTransform += u_Bones[int(a_BoneIndices.z)] * a_BoneWeights.z;\r\n\t\t\tskinTransform += u_Bones[int(a_BoneIndices.w)] * a_BoneWeights.w;\r\n\t\t#endif\r\n\t\tposition=skinTransform*a_Position;\r\n\t #else\r\n\t\tposition=a_Position;\r\n\t#endif\r\n\r\n\tmat4 worldMat;\r\n\t#ifdef GPU_INSTANCE\r\n\t\tworldMat = a_WorldMat;\r\n\t#else\r\n\t\tworldMat = u_WorldMat;\r\n\t#endif\r\n\r\n\t#ifdef GPU_INSTANCE\r\n\t\tgl_Position = u_ViewProjection * worldMat * position;\r\n\t#else\r\n\t\tgl_Position = u_MvpMatrix * position;\r\n\t#endif\r\n\r\n\t\r\n\r\n\tv_PositionWorld=(worldMat*position).xyz;\r\n\r\n\t#if defined(ALBEDOTEXTURE)||defined(METALLICGLOSSTEXTURE)||defined(NORMALTEXTURE)||defined(EMISSIONTEXTURE)||defined(OCCLUSIONTEXTURE)||defined(PARALLAXTEXTURE)\r\n\t\tv_Texcoord0=TransformUV(a_Texcoord0,u_TilingOffset);\r\n\t#endif\r\n\r\n\tv_EyeVec =u_CameraPos-v_PositionWorld;//will normalize per-pixel\r\n\r\n\t#ifdef LIGHTMAP\r\n\t\tvec2 texcoord;\r\n\t\t#ifdef UV1\r\n\t\t\ttexcoord=a_Texcoord1;\r\n\t\t#else\r\n\t\t\ttexcoord=a_Texcoord0;\r\n\t\t#endif\r\n\t\tv_LightMapUV=transformLightMapUV(texcoord,u_LightmapScaleOffset);\r\n\t#endif\r\n\r\n\tmat3 worldInvMat;\r\n\t#ifdef BONE\r\n\t\tworldInvMat=INVERSE_MAT(mat3(worldMat*skinTransform));\r\n\t#else\r\n\t\tworldInvMat=INVERSE_MAT(mat3(worldMat));\r\n\t#endif\r\n\r\n\tv_Normal=normalize(a_Normal*worldInvMat);//if no normalize will cause precision problem.\r\n\r\n\t#ifdef NORMALTEXTURE\r\n\t\tv_Tangent=normalize(a_Tangent0.xyz*worldInvMat);\r\n\t\tv_Binormal=cross(v_Normal,v_Tangent)*a_Tangent0.w;\r\n\t#endif\r\n\r\n\t#ifdef PARALLAXTEXTURE\r\n\t\tvec3 binormal = cross(a_Normal, a_Tangent0.xyz)*a_Tangent0.w;\r\n\t\tmat3 objectTBN = mat3(a_Tangent0.xyz, binormal, a_Normal);\r\n\t\tv_ViewDirForParallax =(u_CameraPos*worldInvMat-position.xyz)*objectTBN;\r\n\t#endif\r\n\r\n\t#if defined(CALCULATE_SHADOWS)&&!defined(SHADOW_CASCADE)\r\n\t\tv_ShadowCoord = getShadowCoord(vec4(v_PositionWorld,1.0));\r\n\t#endif\r\n\r\n\t#if defined(CALCULATE_SPOTSHADOWS)//shader中自定义的宏不可用ifdef 必须改成if defined\r\n\t\tv_SpotShadowCoord = u_SpotViewProjectMatrix*vec4(v_PositionWorld,1.0);\r\n\t#endif\r\n}";
|
||
|
||
var BloomVS = "#include \"Lighting.glsl\";\r\n#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\nattribute vec4 a_PositionTexcoord;\r\nvarying vec2 v_Texcoord0;\r\n\r\nvoid main() {\r\n\tgl_Position = vec4(a_PositionTexcoord.xy, 0.0, 1.0);\r\n\tv_Texcoord0 = a_PositionTexcoord.zw;\r\n\tgl_Position = remapGLPositionZ(gl_Position);\r\n}";
|
||
|
||
var BloomDownsample13PS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\n#include \"Colors.glsl\";\r\n#include \"Sampling.glsl\";\r\n\r\nvarying vec2 v_Texcoord0;\r\n\r\nuniform sampler2D u_MainTex;\r\nuniform vec4 u_MainTex_TexelSize;\r\n\r\nvoid fragDownsample13() {\r\n\tmediump vec4 color = downsampleBox13Tap(u_MainTex, v_Texcoord0, u_MainTex_TexelSize.xy);\r\n\tgl_FragColor = color;\r\n}\r\n\r\nvoid main() {\r\n\tfragDownsample13();\r\n}";
|
||
|
||
var BloomDownsample4PS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\n#include \"Colors.glsl\";\r\n#include \"Sampling.glsl\";\r\n\r\nvarying vec2 v_Texcoord0;\r\n\r\nuniform sampler2D u_MainTex;\r\nuniform vec4 u_MainTex_TexelSize;\r\n\r\nvoid fragDownsample4() {\r\n\tmediump vec4 color = downsampleBox4Tap(u_MainTex, v_Texcoord0, u_MainTex_TexelSize.xy);\r\n\tgl_FragColor = color;\r\n}\r\n\r\nvoid main() {\r\n\tfragDownsample4();\r\n}";
|
||
|
||
var BloomPrefilter13PS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\n#include \"Colors.glsl\";\r\n#include \"Sampling.glsl\";\r\n\r\nvarying vec2 v_Texcoord0;\r\n\r\nuniform sampler2D u_MainTex;\r\nuniform sampler2D u_AutoExposureTex;\r\nuniform vec4 u_MainTex_TexelSize;\r\nuniform vec4 u_Threshold; // x: threshold value (linear), y: threshold - knee, z: knee * 2, w: 0.25 / knee\r\nuniform vec4 u_Params; // x: clamp, yzw: unused\r\n\r\nmediump vec4 prefilter(mediump vec4 color, vec2 uv) {\r\n\tmediump float autoExposure = texture2D(u_AutoExposureTex, uv).r;\r\n\tcolor *= autoExposure;\r\n\tcolor = min(vec4(u_Params.x), color); // clamp to max\r\n\tcolor = quadraticThreshold(color, u_Threshold.x, u_Threshold.yzw);\r\n\treturn color;\r\n}\r\n\r\nvoid fragPrefilter13() {\r\n\tmediump vec4 color = downsampleBox13Tap(u_MainTex, v_Texcoord0, u_MainTex_TexelSize.xy);\r\n\tgl_FragColor = prefilter(safeHDR(color), v_Texcoord0);\r\n}\r\n\r\nvoid main() {\r\n\tfragPrefilter13();\r\n}";
|
||
|
||
var BloomPrefilter4PS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\n#include \"Colors.glsl\";\r\n#include \"Sampling.glsl\";\r\n\r\nvarying vec2 v_Texcoord0;\r\n\r\nuniform sampler2D u_MainTex;\r\nuniform sampler2D u_AutoExposureTex;\r\nuniform vec4 u_MainTex_TexelSize;\r\nuniform vec4 u_Threshold; // x: threshold value (linear), y: threshold - knee, z: knee * 2, w: 0.25 / knee\r\nuniform vec4 u_Params; // x: clamp, yzw: unused\r\n\r\nmediump vec4 prefilter(mediump vec4 color, vec2 uv) {\r\n\tmediump float autoExposure = texture2D(u_AutoExposureTex, uv).r;\r\n\tcolor *= autoExposure;\r\n\tcolor = min(vec4(u_Params.x), color); // clamp to max\r\n\tcolor = quadraticThreshold(color, u_Threshold.x, u_Threshold.yzw);\r\n\treturn color;\r\n}\r\n\r\nvoid fragPrefilter4() {\r\n\tmediump vec4 color = downsampleBox4Tap(u_MainTex, v_Texcoord0, u_MainTex_TexelSize.xy);\r\n\tgl_FragColor = prefilter(safeHDR(color), v_Texcoord0);\r\n}\r\n\r\nvoid main() {\r\n\tfragPrefilter4();\r\n}";
|
||
|
||
var BloomUpsampleBoxPS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\n#include \"Colors.glsl\";\r\n#include \"Sampling.glsl\";\r\n\r\nvarying vec2 v_Texcoord0;\r\n\r\nuniform sampler2D u_MainTex;\r\nuniform sampler2D u_BloomTex;\r\n\r\nuniform vec4 u_MainTex_TexelSize;\r\nuniform float u_SampleScale;\r\n\r\nmediump vec4 combine(mediump vec4 bloom, vec2 uv) {\r\n\tmediump vec4 color = texture2D(u_BloomTex, uv);\r\n\treturn bloom + color;\r\n}\r\n\r\nvoid fragUpsampleBox() {\r\n\tmediump vec4 bloom = upsampleBox(u_MainTex, v_Texcoord0, u_MainTex_TexelSize.xy, vec4(u_SampleScale));\r\n\tgl_FragColor = combine(bloom, v_Texcoord0);\r\n}\r\n\r\nvoid main() {\r\n\tfragUpsampleBox();\r\n}";
|
||
|
||
var BloomUpsampleTentPS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\n#include \"Colors.glsl\";\r\n#include \"Sampling.glsl\";\r\n\r\nvarying vec2 v_Texcoord0;\r\n\r\nuniform sampler2D u_MainTex;\r\nuniform sampler2D u_BloomTex;\r\n\r\nuniform vec4 u_MainTex_TexelSize;\r\nuniform float u_SampleScale;\r\n\r\nmediump vec4 combine(mediump vec4 bloom, vec2 uv) {\r\n\tmediump vec4 color = texture2D(u_BloomTex, uv);\r\n\treturn bloom + color;\r\n}\r\n\r\nvoid fragUpsampleTent() {\r\n\tmediump vec4 bloom = upsampleTent(u_MainTex, v_Texcoord0, u_MainTex_TexelSize.xy, vec4(u_SampleScale));\r\n\tgl_FragColor = combine(bloom, v_Texcoord0);\r\n}\r\n\r\nvoid main() {\r\n\tfragUpsampleTent();\r\n}";
|
||
|
||
var ColorsGLSL = "#include \"StdLib.glsl\";\r\n\r\n#define EPSILON 1.0e-4\r\n\r\n// Quadratic color thresholding\r\n// curve = (threshold - knee, knee * 2, 0.25 / knee)\r\nmediump vec4 quadraticThreshold(mediump vec4 color, mediump float threshold, mediump vec3 curve) {\r\n\t// Pixel brightness\r\n\tmediump float br = max3(color.r, color.g, color.b);\r\n\r\n\t// Under-threshold part: quadratic curve\r\n\tmediump float rq = clamp(br - curve.x, 0.0, curve.y);\r\n\trq = curve.z * rq * rq;\r\n\r\n\t// Combine and apply the brightness response curve.\r\n\tcolor *= max(rq, br - threshold) / max(br, EPSILON);\r\n\r\n\treturn color;\r\n}\r\n\r\n\r\n\r\n//\r\n// sRGB transfer functions\r\n// Fast path ref: http://chilliant.blogspot.com.au/2012/08/srgb-approximations-for-hlsl.html?m=1\r\n//\r\nmediump vec3 sRGBToLinear(mediump vec3 c) {\r\n\t#ifdef USE_VERY_FAST_SRGB\r\n\t\treturn c * c;\r\n\t#elif defined(USE_FAST_SRGB)\r\n\t\treturn c * (c * (c * 0.305306011 + 0.682171111) + 0.012522878);\r\n\t#else\r\n\t\tmediump vec3 linearRGBLo = c / 12.92;\r\n\t\tmediump vec3 power=vec3(2.4, 2.4, 2.4);\r\n\t\tmediump vec3 linearRGBHi = positivePow((c + 0.055) / 1.055, power);\r\n\t\tmediump vec3 linearRGB =vec3((c.r<=0.04045) ? linearRGBLo.r : linearRGBHi.r,(c.g<=0.04045) ? linearRGBLo.g : linearRGBHi.g,(c.b<=0.04045) ? linearRGBLo.b : linearRGBHi.b);\r\n\t\treturn linearRGB;\r\n\t#endif\r\n}\r\n\r\nmediump vec4 sRGBToLinear(mediump vec4 c){\r\n return vec4(sRGBToLinear(c.rgb), c.a);\r\n}\r\n\r\n\r\n\r\nmediump vec3 linearToSRGB(mediump vec3 c) {\r\n\t#ifdef USE_VERY_FAST_SRGB\r\n\t\treturn sqrt(c);\r\n\t#elif defined(USE_FAST_SRGB)\r\n\t\treturn max(1.055 * PositivePow(c, 0.416666667) - 0.055, 0.0);\r\n\t#else\r\n\t\tmediump vec3 sRGBLo = c * 12.92;\r\n\t\tmediump vec3 power=vec3(1.0 / 2.4, 1.0 / 2.4, 1.0 / 2.4);\r\n\t\tmediump vec3 sRGBHi = (positivePow(c, power) * 1.055) - 0.055;\r\n\t\tmediump vec3 sRGB =vec3((c.r<=0.0031308) ? sRGBLo.r : sRGBHi.r,(c.g<=0.0031308) ? sRGBLo.g : sRGBHi.g,(c.b<=0.0031308) ? sRGBLo.b : sRGBHi.b);\r\n\t\treturn sRGB;\r\n\t#endif\r\n}\r\n\r\nmediump vec4 linearToSRGB(mediump vec4 c){\r\n return vec4(linearToSRGB(c.rgb), c.a);\r\n}";
|
||
|
||
var CompositePS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\n#include \"Colors.glsl\";\r\n#include \"Sampling.glsl\";\r\n\r\nvarying vec2 v_Texcoord0;\r\n\r\nuniform sampler2D u_MainTex;\r\nuniform sampler2D u_BloomTex;\r\n\r\nuniform sampler2D u_AutoExposureTex;\r\nuniform sampler2D u_Bloom_DirtTex;\r\nuniform vec4 u_BloomTex_TexelSize;\r\nuniform vec4 u_Bloom_DirtTileOffset; // xy: tiling, zw: offset\r\nuniform mediump vec3 u_Bloom_Settings;// x: sampleScale, y: intensity, z: dirt intensity\r\nuniform mediump vec3 u_Bloom_Color;\r\n\r\nvoid main() {\r\n\tmediump float autoExposure = texture2D(u_AutoExposureTex, v_Texcoord0).r;\r\n\tmediump vec4 color=vec4(0.0);\r\n\tcolor = texture2D(u_MainTex, v_Texcoord0);\r\n\t\r\n\tcolor = sRGBToLinear(color);\r\n\tcolor.rgb *= autoExposure;\r\n\t\r\n\t#if defined(BLOOM)||defined(BLOOM_LOW)\r\n\t\t#ifdef BLOOM\r\n\t\t\tmediump vec4 bloom = upsampleTent(u_BloomTex, v_Texcoord0, u_BloomTex_TexelSize.xy, vec4(u_Bloom_Settings.x));\r\n\t\t#else\r\n\t\t\tmediump vec4 bloom = upsampleBox(u_BloomTex, v_Texcoord0, u_BloomTex_TexelSize.xy, vec4(u_Bloom_Settings.x));\r\n\t\t#endif\r\n\r\n\t\t// UVs should be Distort(uv * u_Bloom_DirtTileOffset.xy + u_Bloom_DirtTileOffset.zw)\r\n\t\t// but considering we use a cover-style scale on the dirt texture the difference\r\n\t\t// isn't massive so we chose to save a few ALUs here instead in case lens distortion\r\n\t\t// is active\r\n\t\tmediump vec4 dirt =vec4(texture2D(u_Bloom_DirtTex, v_Texcoord0 * u_Bloom_DirtTileOffset.xy + u_Bloom_DirtTileOffset.zw).rgb, 0.0);\r\n\r\n\t\t// Additive bloom (artist friendly)\r\n\t\tbloom *= u_Bloom_Settings.y;\r\n\t\tdirt *= u_Bloom_Settings.z;\r\n\t\tmediump vec4 bloomColor=vec4(u_Bloom_Color, 1.0);\r\n\t\tcolor += bloom * bloomColor;\r\n\t\tcolor += dirt * bloom;\r\n\t#endif\r\n\t\r\n\tmediump vec4 finalColor = color;\r\n\tfinalColor = linearToSRGB(finalColor);\r\n\t//finalColor.rgb = Dither(finalColor.rgb, v_Texcoord0);//TODO:抖动\r\n\tgl_FragColor = finalColor;\r\n}";
|
||
|
||
var CompositeVS = "#include \"Lighting.glsl\";\r\n\r\nattribute vec4 a_PositionTexcoord;\r\nvarying vec2 v_Texcoord0;\r\n\r\nvoid main() {\r\n\tgl_Position = vec4(a_PositionTexcoord.xy, 0.0, 1.0);\r\n\tv_Texcoord0 = a_PositionTexcoord.zw;\r\n\tgl_Position = remapGLPositionZ(gl_Position);\r\n}";
|
||
|
||
var SamplingGLSL = "// Better, temporally stable box filtering\r\n// [Jimenez14] http://goo.gl/eomGso\r\n// . . . . . . .\r\n// . A . B . C .\r\n// . . D . E . .\r\n// . F . G . H .\r\n// . . I . J . .\r\n// . K . L . M .\r\n// . . . . . . .\r\nmediump vec4 downsampleBox13Tap(sampler2D tex, vec2 uv, vec2 texelSize)\r\n{\r\n mediump vec4 A = texture2D(tex, uv + texelSize * vec2(-1.0, -1.0));\r\n mediump vec4 B = texture2D(tex, uv + texelSize * vec2( 0.0, -1.0));\r\n mediump vec4 C = texture2D(tex, uv + texelSize * vec2( 1.0, -1.0));\r\n mediump vec4 D = texture2D(tex, uv + texelSize * vec2(-0.5, -0.5));\r\n mediump vec4 E = texture2D(tex, uv + texelSize * vec2( 0.5, -0.5));\r\n mediump vec4 F = texture2D(tex, uv + texelSize * vec2(-1.0, 0.0));\r\n mediump vec4 G = texture2D(tex, uv);\r\n mediump vec4 H = texture2D(tex, uv + texelSize * vec2( 1.0, 0.0));\r\n mediump vec4 I = texture2D(tex, uv + texelSize * vec2(-0.5, 0.5));\r\n mediump vec4 J = texture2D(tex, uv + texelSize * vec2( 0.5, 0.5));\r\n mediump vec4 K = texture2D(tex, uv + texelSize * vec2(-1.0, 1.0));\r\n mediump vec4 L = texture2D(tex, uv + texelSize * vec2( 0.0, 1.0));\r\n mediump vec4 M = texture2D(tex, uv + texelSize * vec2( 1.0, 1.0));\r\n\r\n\tmediump vec2 scale= vec2(0.5, 0.125);\r\n mediump vec2 div = (1.0 / 4.0) * scale;\r\n\r\n mediump vec4 o = (D + E + I + J) * div.x;\r\n o += (A + B + G + F) * div.y;\r\n o += (B + C + H + G) * div.y;\r\n o += (F + G + L + K) * div.y;\r\n o += (G + H + M + L) * div.y;\r\n\r\n return o;\r\n}\r\n\r\n// Standard box filtering\r\nmediump vec4 downsampleBox4Tap(sampler2D tex, vec2 uv, vec2 texelSize)\r\n{\r\n vec4 d = texelSize.xyxy * vec4(-1.0, -1.0, 1.0, 1.0);\r\n\r\n mediump vec4 s = texture2D(tex, uv + d.xy);\r\n s += texture2D(tex, uv + d.zy);\r\n s += texture2D(tex, uv + d.xw);\r\n s += texture2D(tex, uv + d.zw);\r\n\r\n return s * (1.0 / 4.0);\r\n}\r\n\r\n// 9-tap bilinear upsampler (tent filter)\r\n// . . . . . . .\r\n// . 1 . 2 . 1 .\r\n// . . . . . . .\r\n// . 2 . 4 . 2 .\r\n// . . . . . . .\r\n// . 1 . 2 . 1 .\r\n// . . . . . . .\r\nmediump vec4 upsampleTent(sampler2D tex, vec2 uv, vec2 texelSize, vec4 sampleScale)\r\n{\r\n vec4 d = texelSize.xyxy * vec4(1.0, 1.0, -1.0, 0.0) * sampleScale;\r\n\r\n mediump vec4 s = texture2D(tex, uv - d.xy);\r\n s += texture2D(tex, uv - d.wy) * 2.0;\r\n s += texture2D(tex, uv - d.zy);\r\n\r\n s += texture2D(tex, uv + d.zw) * 2.0;\r\n s += texture2D(tex, uv) * 4.0;\r\n s += texture2D(tex,\tuv + d.xw) * 2.0;\r\n\r\n s += texture2D(tex, uv + d.zy);\r\n s += texture2D(tex, uv + d.wy) * 2.0;\r\n s += texture2D(tex, uv + d.xy);\r\n\r\n return s * (1.0 / 16.0);\r\n}\r\n\r\n// Standard box filtering\r\nmediump vec4 upsampleBox(sampler2D tex, vec2 uv, vec2 texelSize, vec4 sampleScale)\r\n{\r\n vec4 d = texelSize.xyxy * vec4(-1.0, -1.0, 1.0, 1.0) * 0.5 * sampleScale;\r\n\r\n mediump vec4 s = texture2D(tex, uv + d.xy);\r\n s += texture2D(tex, uv + d.zy);\r\n s += texture2D(tex, uv + d.xw);\r\n s += texture2D(tex, uv + d.zw);\r\n\r\n return s * (1.0 / 4.0);\r\n}";
|
||
|
||
var StdLibGLSL = "#define HALF_MAX 65504.0 // (2 - 2^-10) * 2^15\r\n\r\n#define FLT_EPSILON 1.192092896e-07 // Smallest positive number, such that 1.0 + FLT_EPSILON != 1.0\r\n\r\nmediump vec4 safeHDR(mediump vec4 c)\r\n{\r\n return min(c, HALF_MAX);\r\n}\r\n\r\nfloat max3(float a, float b, float c)\r\n{\r\n return max(max(a, b), c);\r\n}\r\n\r\nvec3 positivePow(vec3 base, vec3 power)\r\n{\r\n return pow(max(abs(base), vec3(FLT_EPSILON, FLT_EPSILON, FLT_EPSILON)), power);\r\n}";
|
||
|
||
var ShadowGLSL = "#ifndef GRAPHICS_API_GLES3\r\n\t#define NO_NATIVE_SHADOWMAP\r\n#endif\r\n\r\n#if defined(NO_NATIVE_SHADOWMAP)\r\n\t#define TEXTURE2D_SHADOW(textureName) uniform mediump sampler2D textureName\r\n\t#define SAMPLE_TEXTURE2D_SHADOW(textureName, coord3) (texture2D(textureName,coord3.xy).r<coord3.z?0.0:1.0)\r\n\t#define TEXTURE2D_SHADOW_PARAM(shadowMap) mediump sampler2D shadowMap\r\n#else\r\n\t#define TEXTURE2D_SHADOW(textureName) uniform mediump sampler2DShadow textureName\r\n\t#define SAMPLE_TEXTURE2D_SHADOW(textureName, coord3) textureLod(textureName,coord3,0.0)\r\n\t#define TEXTURE2D_SHADOW_PARAM(shadowMap) mediump sampler2DShadow shadowMap\r\n#endif\r\n\r\n#if defined(RECEIVESHADOW)&&defined(SHADOW)\r\n #define CALCULATE_SHADOWS\r\n#endif\r\n\r\n#if defined(RECEIVESHADOW)&&defined(SHADOW_SPOT)\r\n\t#define CALCULATE_SPOTSHADOWS\r\n#endif\r\n\r\nuniform vec4 u_ShadowBias; // x: depth bias, y: normal bias\r\n\r\n#if defined(CALCULATE_SHADOWS)||defined(CALCULATE_SPOTSHADOWS)\r\n\t#include \"ShadowSampleTent.glsl\"\r\n\tuniform vec4 u_ShadowMapSize;\r\n\tuniform vec4 u_SpotShadowMapSize;\r\n\tuniform vec4 u_ShadowParams; // x: shadowStrength y: ShadowSpotLightStrength\r\n\t\r\n\tfloat sampleShdowMapFiltered4(TEXTURE2D_SHADOW_PARAM(shadowMap),vec3 shadowCoord,vec4 shadowMapSize)\r\n\t{\r\n\t\tfloat attenuation;\r\n\t\tvec4 attenuation4;\r\n\t\tvec2 offset=shadowMapSize.xy/2.0;\r\n\t\tvec3 shadowCoord0=shadowCoord + vec3(-offset,0.0);\r\n\t\tvec3 shadowCoord1=shadowCoord + vec3(offset.x,-offset.y,0.0);\r\n\t\tvec3 shadowCoord2=shadowCoord + vec3(-offset.x,offset.y,0.0);\r\n\t\tvec3 shadowCoord3=shadowCoord + vec3(offset,0.0);\r\n\t\tattenuation4.x = SAMPLE_TEXTURE2D_SHADOW(shadowMap, shadowCoord0);\r\n\t\tattenuation4.y = SAMPLE_TEXTURE2D_SHADOW(shadowMap, shadowCoord1);\r\n\t\tattenuation4.z = SAMPLE_TEXTURE2D_SHADOW(shadowMap, shadowCoord2);\r\n\t\tattenuation4.w = SAMPLE_TEXTURE2D_SHADOW(shadowMap, shadowCoord3);\r\n\t\tattenuation = dot(attenuation4, vec4(0.25));\r\n\t\treturn attenuation;\r\n\t}\r\n\r\n\tfloat sampleShdowMapFiltered9(TEXTURE2D_SHADOW_PARAM(shadowMap),vec3 shadowCoord,vec4 shadowmapSize)\r\n\t{\r\n\t\tfloat attenuation;\r\n\t\tfloat fetchesWeights[9];\r\n\t\tvec2 fetchesUV[9];\r\n\t\tsampleShadowComputeSamplesTent5x5(shadowmapSize, shadowCoord.xy, fetchesWeights, fetchesUV);\r\n\t\tattenuation = fetchesWeights[0] * SAMPLE_TEXTURE2D_SHADOW(shadowMap, vec3(fetchesUV[0].xy, shadowCoord.z));\r\n\t\tattenuation += fetchesWeights[1] * SAMPLE_TEXTURE2D_SHADOW(shadowMap, vec3(fetchesUV[1].xy, shadowCoord.z));\r\n\t\tattenuation += fetchesWeights[2] * SAMPLE_TEXTURE2D_SHADOW(shadowMap, vec3(fetchesUV[2].xy, shadowCoord.z));\r\n\t\tattenuation += fetchesWeights[3] * SAMPLE_TEXTURE2D_SHADOW(shadowMap, vec3(fetchesUV[3].xy, shadowCoord.z));\r\n\t\tattenuation += fetchesWeights[4] * SAMPLE_TEXTURE2D_SHADOW(shadowMap, vec3(fetchesUV[4].xy, shadowCoord.z));\r\n\t\tattenuation += fetchesWeights[5] * SAMPLE_TEXTURE2D_SHADOW(shadowMap, vec3(fetchesUV[5].xy, shadowCoord.z));\r\n\t\tattenuation += fetchesWeights[6] * SAMPLE_TEXTURE2D_SHADOW(shadowMap, vec3(fetchesUV[6].xy, shadowCoord.z));\r\n\t\tattenuation += fetchesWeights[7] * SAMPLE_TEXTURE2D_SHADOW(shadowMap, vec3(fetchesUV[7].xy, shadowCoord.z));\r\n\t\tattenuation += fetchesWeights[8] * SAMPLE_TEXTURE2D_SHADOW(shadowMap, vec3(fetchesUV[8].xy, shadowCoord.z));\r\n\t\treturn attenuation;\r\n\t}\r\n\r\n#endif\r\n\r\n\r\n\r\n\r\n#if defined(CALCULATE_SHADOWS)\r\n\r\n\tTEXTURE2D_SHADOW(u_ShadowMap);\r\n\r\n\tuniform mat4 u_ShadowMatrices[4];\r\n\tuniform vec4 u_ShadowSplitSpheres[4];// max cascade is 4\r\n\r\n\tmediump int computeCascadeIndex(vec3 positionWS)\r\n\t{\r\n\t\tvec3 fromCenter0 = positionWS - u_ShadowSplitSpheres[0].xyz;\r\n\t\tvec3 fromCenter1 = positionWS - u_ShadowSplitSpheres[1].xyz;\r\n\t\tvec3 fromCenter2 = positionWS - u_ShadowSplitSpheres[2].xyz;\r\n\t\tvec3 fromCenter3 = positionWS - u_ShadowSplitSpheres[3].xyz;\r\n\r\n\t\tmediump vec4 comparison = vec4(\r\n\t\t\tdot(fromCenter0, fromCenter0)<u_ShadowSplitSpheres[0].w,\r\n\t\t\tdot(fromCenter1, fromCenter1)<u_ShadowSplitSpheres[1].w,\r\n\t\t\tdot(fromCenter2, fromCenter2)<u_ShadowSplitSpheres[2].w,\r\n\t\t\tdot(fromCenter3, fromCenter3)<u_ShadowSplitSpheres[3].w);\r\n\t\tcomparison.yzw = clamp(comparison.yzw - comparison.xyz,0.0,1.0);//keep the nearest\r\n\t\tmediump vec4 indexCoefficient = vec4(4.0,3.0,2.0,1.0);\r\n\t\tmediump int index = 4 - int(dot(comparison, indexCoefficient));\r\n\t\treturn index;\r\n\t}\r\n\r\n\tvec4 getShadowCoord(vec4 positionWS)\r\n\t{\r\n\t\t#ifdef SHADOW_CASCADE\r\n\t\t\tmediump int cascadeIndex = computeCascadeIndex(positionWS.xyz);\r\n\t\t\tif(cascadeIndex > 3)// out of shadow range cascadeIndex is 4.\r\n\t\t\t\treturn vec4(0.0);\r\n\t\t\t\r\n\t\t\t#ifdef GRAPHICS_API_GLES3\r\n\t\t\t\treturn u_ShadowMatrices[cascadeIndex] * positionWS;\r\n\t\t\t#else\r\n\t\t\t\tmat4 shadowMat;\r\n\t\t\t\tif(cascadeIndex == 0)\r\n\t\t\t\t\tshadowMat = u_ShadowMatrices[0];\r\n\t\t\t\telse if(cascadeIndex == 1)\r\n\t\t\t\t\tshadowMat = u_ShadowMatrices[1];\r\n\t\t\t\telse if(cascadeIndex == 2)\r\n\t\t\t\t\tshadowMat = u_ShadowMatrices[2];\r\n\t\t\t\telse\r\n\t\t\t\t\tshadowMat = u_ShadowMatrices[3];\r\n\t\t\t\treturn shadowMat * positionWS;\r\n\t\t\t#endif\r\n\t\t#else\r\n\t\t\treturn u_ShadowMatrices[0] * positionWS;\r\n\t\t#endif\r\n\t}\r\n\r\n\tfloat sampleShadowmap(vec4 shadowCoord)\r\n\t{\r\n\t\tshadowCoord.xyz /= shadowCoord.w;\r\n\t\tfloat attenuation = 1.0;\r\n\t\tif(shadowCoord.z > 0.0 && shadowCoord.z < 1.0)\r\n\t\t{\r\n\t\t\t#if defined(SHADOW_SOFT_SHADOW_HIGH)\r\n\t\t\t\tattenuation = sampleShdowMapFiltered9(u_ShadowMap,shadowCoord.xyz,u_ShadowMapSize);\r\n\t\t\t#elif defined(SHADOW_SOFT_SHADOW_LOW)\r\n\t\t\t\tattenuation = sampleShdowMapFiltered4(u_ShadowMap,shadowCoord.xyz,u_ShadowMapSize);\r\n\t\t\t#else\r\n\t\t\t\tattenuation = SAMPLE_TEXTURE2D_SHADOW(u_ShadowMap,shadowCoord.xyz);\r\n\t\t\t#endif\r\n\t\t\tattenuation = mix(1.0,attenuation,u_ShadowParams.x);//shadowParams.x:shadow strength\r\n\t\t}\r\n\t\treturn attenuation;\r\n\t}\r\n#endif\r\n\r\n#if defined(CALCULATE_SPOTSHADOWS)//shader<65><72><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD>ĺ겻<C4BA><EAB2BB><EFBFBD><EFBFBD>ifdef <20><><EFBFBD><EFBFBD>ij<EFBFBD>if defined\r\n\tTEXTURE2D_SHADOW(u_SpotShadowMap);\r\n\tuniform mat4 u_SpotViewProjectMatrix;\r\n\tfloat sampleSpotShadowmap(vec4 shadowCoord)\r\n\t{\r\n\t\tshadowCoord.xyz /= shadowCoord.w;\r\n\t\tfloat attenuation = 1.0;\r\n\t\tshadowCoord.xy +=1.0;\r\n\t\tshadowCoord.xy/=2.0; \r\n\t\tif(shadowCoord.z > 0.0 && shadowCoord.z < 1.0)\r\n\t\t{\r\n\t\t\t#if defined(SHADOW_SPOT_SOFT_SHADOW_HIGH)\r\n\t\t\t\tattenuation = sampleShdowMapFiltered9(u_SpotShadowMap,shadowCoord.xyz,u_SpotShadowMapSize);\r\n\t\t\t#elif defined(SHADOW_SPOT_SOFT_SHADOW_LOW)\r\n\t\t\t\tattenuation = sampleShdowMapFiltered4(u_SpotShadowMap,shadowCoord.xyz,u_SpotShadowMapSize);\r\n\t\t\t#else\r\n\t\t\t\tattenuation = SAMPLE_TEXTURE2D_SHADOW(u_SpotShadowMap,shadowCoord.xyz);\r\n\t\t\t#endif\r\n\t\t\tattenuation = mix(1.0,attenuation,u_ShadowParams.y);//shadowParams.y:shadow strength\r\n\t\t}\r\n\t\treturn attenuation;\r\n\t}\r\n#endif\r\n\r\nvec3 applyShadowBias(vec3 positionWS, vec3 normalWS, vec3 lightDirection)\r\n{\r\n float invNdotL = 1.0 - clamp(dot(-lightDirection, normalWS),0.0,1.0);\r\n float scale = invNdotL * u_ShadowBias.y;\r\n\r\n // normal bias is negative since we want to apply an inset normal offset\r\n positionWS += -lightDirection * u_ShadowBias.xxx;\r\n positionWS += normalWS * vec3(scale);\r\n return positionWS;\r\n}\r\n";
|
||
|
||
var ShadowCasterVSGLSL = "#include \"Lighting.glsl\";\r\n#include \"LayaUtile.glsl\"\r\n#include \"Shadow.glsl\"\r\n\r\nattribute vec4 a_Position;\r\nattribute vec3 a_Normal;\r\n\r\n#ifdef BONE\r\n\tconst int c_MaxBoneCount = 24;\r\n\tattribute vec4 a_BoneIndices;\r\n\tattribute vec4 a_BoneWeights;\r\n\tuniform mat4 u_Bones[c_MaxBoneCount];\r\n#endif\r\n\r\n#ifdef GPU_INSTANCE\r\n\tattribute mat4 a_WorldMat;\r\n#else\r\n\tuniform mat4 u_WorldMat;\r\n#endif\r\n\r\nuniform mat4 u_ViewProjection;\r\n\r\n#ifdef SHADOW\r\n\tuniform vec3 u_ShadowLightDirection;\r\n#endif\r\n\r\n\r\nvec4 shadowCasterVertex()\r\n{\r\n\tmat4 worldMat;\r\n\t#ifdef GPU_INSTANCE\r\n\t\tworldMat = a_WorldMat;\r\n\t#else\r\n\t\tworldMat = u_WorldMat;\r\n\t#endif\r\n\t\r\n\t#ifdef BONE\r\n\t\tmat4 skinTransform;\r\n\t \t#ifdef SIMPLEBONE\r\n\t\t\tfloat currentPixelPos;\r\n\t\t\t#ifdef GPU_INSTANCE\r\n\t\t\t\tcurrentPixelPos = a_SimpleTextureParams.x+a_SimpleTextureParams.y;\r\n\t\t\t#else\r\n\t\t\t\tcurrentPixelPos = u_SimpleAnimatorParams.x+u_SimpleAnimatorParams.y;\r\n\t\t\t#endif\r\n\t\t\tfloat offset = 1.0/u_SimpleAnimatorTextureSize;\r\n\t\t\tskinTransform = loadMatFromTexture(currentPixelPos,int(a_BoneIndices.x),offset) * a_BoneWeights.x;\r\n\t\t\tskinTransform += loadMatFromTexture(currentPixelPos,int(a_BoneIndices.y),offset) * a_BoneWeights.y;\r\n\t\t\tskinTransform += loadMatFromTexture(currentPixelPos,int(a_BoneIndices.z),offset) * a_BoneWeights.z;\r\n\t\t\tskinTransform += loadMatFromTexture(currentPixelPos,int(a_BoneIndices.w),offset) * a_BoneWeights.w;\r\n\t\t#else\r\n\t\t\tskinTransform = u_Bones[int(a_BoneIndices.x)] * a_BoneWeights.x;\r\n\t\t\tskinTransform += u_Bones[int(a_BoneIndices.y)] * a_BoneWeights.y;\r\n\t\t\tskinTransform += u_Bones[int(a_BoneIndices.z)] * a_BoneWeights.z;\r\n\t\t\tskinTransform += u_Bones[int(a_BoneIndices.w)] * a_BoneWeights.w;\r\n\t\t#endif\r\n\t\tworldMat = worldMat * skinTransform;\r\n\t#endif\r\n\r\n\tvec4 positionWS = worldMat * a_Position;\r\n\tmat3 worldInvMat;\r\n\t#ifdef BONE\r\n\t\tworldInvMat=INVERSE_MAT(mat3(worldMat*skinTransform));\r\n\t#else\r\n\t\tworldInvMat=INVERSE_MAT(mat3(worldMat));\r\n\t#endif \r\n\r\n\tvec3 normalWS = normalize(a_Normal*worldInvMat);//if no normalize will cause precision problem\r\n\tvec4 positionCS = u_ViewProjection * positionWS;\r\n\t#ifdef SHADOW\r\n\t\tpositionWS.xyz = applyShadowBias(positionWS.xyz,normalWS,u_ShadowLightDirection);\r\n\t\tpositionCS.z = max(positionCS.z, 0.0);//min ndc z is 0.0\r\n\t#endif\r\n\r\n\t\r\n\t#ifdef SHADOW_SPOT\r\n\t\tpositionCS.z = positionCS.z-u_ShadowBias.x/positionCS.w;\r\n\t\tpositionCS.z = max(positionCS.z, 0.0);//min ndc z is 0.0\r\n\t#endif\r\n\t\r\n\t\r\n\t// //TODO没考虑UV动画呢\r\n\t// #if defined(DIFFUSEMAP)&&defined(ALPHATEST)\r\n\t// \tv_Texcoord0=a_Texcoord0;\r\n\t// #endif\r\n return positionCS;\r\n}\r\n";
|
||
|
||
var ShadowCasterFSGLSL = "vec4 shadowCasterFragment()\r\n{\r\n return vec4(0.0);\r\n}\r\n";
|
||
|
||
var SkyBoxPS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\nprecision highp float;\r\n#else\r\nprecision mediump float;\r\n#endif\r\n\r\nvarying vec3 v_Texcoord;\r\n\r\nuniform samplerCube u_CubeTexture;\r\nuniform float u_Exposure;\r\nuniform vec4 u_TintColor;\r\n\r\n\r\nvoid main()\r\n{\t\r\n\tvec3 color=textureCube(u_CubeTexture, v_Texcoord).rgb*u_TintColor.rgb*u_Exposure*2.0;\r\n\tgl_FragColor=vec4(color,1.0);\r\n}\r\n\r\n";
|
||
|
||
var SkyBoxVS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\nprecision highp float;\r\n#else\r\nprecision mediump float;\r\n#endif\r\n#include \"Lighting.glsl\";\r\n\r\nattribute vec4 a_Position;\r\nuniform mat4 u_ViewProjection;\r\nuniform float u_Rotation;\r\nvarying vec3 v_Texcoord;\r\n\r\n\r\nvec4 rotateAroundYInDegrees (vec4 vertex, float degrees)\r\n{\r\n\tfloat angle = degrees * 3.141593 / 180.0;\r\n\tfloat sina=sin(angle);\r\n\tfloat cosa=cos(angle);\r\n\tmat2 m = mat2(cosa, -sina, sina, cosa);\r\n\treturn vec4(m*vertex.xz, vertex.yw).xzyw;\r\n}\r\n\t\t\r\nvoid main()\r\n{\r\n\tvec4 position=rotateAroundYInDegrees(a_Position,u_Rotation);\r\n\tgl_Position = u_ViewProjection*position;\r\n\tv_Texcoord=vec3(-a_Position.x,a_Position.yz);//转换坐标系\r\n\tgl_Position=remapGLPositionZ(gl_Position);\r\n}\r\n";
|
||
|
||
var SkyBoxProceduralPS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\n#include \"Lighting.glsl\";\r\n\r\nconst float MIE_G = -0.990;\r\nconst float MIE_G2 = 0.9801;\r\nconst float SKY_GROUND_THRESHOLD = 0.02;\r\n\r\nuniform float u_SunSize;\r\nuniform float u_SunSizeConvergence;\r\nuniform DirectionLight u_SunLight;\r\n\r\n\r\nvarying vec3 v_GroundColor;\r\nvarying vec3 v_SkyColor;\r\n\r\n\r\n#ifdef SUN_HIGH_QUALITY\r\n\tvarying vec3 v_Vertex;\r\n#elif defined(SUN_SIMPLE)\r\n\tvarying vec3 v_RayDir;\r\n#else\r\n\tvarying float v_SkyGroundFactor;\r\n#endif\r\n\r\n#if defined(SUN_HIGH_QUALITY)||defined(SUN_SIMPLE)\r\n\tvarying vec3 v_SunColor;\r\n#endif\r\n\r\n// Calculates the Mie phase function\r\nfloat getMiePhase(float eyeCos, float eyeCos2) {\r\n\tfloat temp = 1.0 + MIE_G2 - 2.0 * MIE_G * eyeCos;\r\n\ttemp = pow(temp, pow(u_SunSize,0.65) * 10.0);\r\n\ttemp = max(temp,1.0e-4); // prevent division by zero, esp. in half precision\r\n\ttemp = 1.5 * ((1.0 - MIE_G2) / (2.0 + MIE_G2)) * (1.0 + eyeCos2) / temp;\r\n\treturn temp;\r\n}\r\n\r\n// Calculates the sun shape\r\nfloat calcSunAttenuation(vec3 lightPos, vec3 ray) {\r\n\t#ifdef SUN_HIGH_QUALITY\r\n\t\tfloat focusedEyeCos = pow(clamp(dot(lightPos, ray),0.0,1.0), u_SunSizeConvergence);\r\n\t\treturn getMiePhase(-focusedEyeCos, focusedEyeCos * focusedEyeCos);\r\n\t#else //SUN_SIMPLE\r\n\t\tvec3 delta = lightPos - ray;\r\n\t\tfloat dist = length(delta);\r\n\t\tfloat spot = 1.0 - smoothstep(0.0, u_SunSize, dist);\r\n\t\treturn spot * spot;\r\n\t#endif\r\n}\r\n\r\nvoid main() {\r\n\t// if y > 1 [eyeRay.y < -SKY_GROUND_THRESHOLD] - ground\r\n\t// if y >= 0 and < 1 [eyeRay.y <= 0 and > -SKY_GROUND_THRESHOLD] - horizon\r\n\t// if y < 0 [eyeRay.y > 0] - sky\r\n\tvec3 col = vec3(0.0, 0.0, 0.0);\r\n\r\n\t#ifdef SUN_HIGH_QUALITY\r\n\t\tvec3 ray = normalize(v_Vertex);\r\n\t\tfloat y = ray.y / SKY_GROUND_THRESHOLD;\r\n\t#elif defined(SUN_SIMPLE) \r\n\t\tvec3 ray = v_RayDir;\r\n\t\tfloat y = ray.y / SKY_GROUND_THRESHOLD;\t\r\n\t#else\r\n\t\tfloat y = v_SkyGroundFactor;\r\n\t#endif\r\n\r\n\t// if we did precalculate color in vprog: just do lerp between them\r\n\tcol = mix(v_SkyColor, v_GroundColor, clamp(y,0.0,1.0));\r\n\r\n\t#if defined(SUN_HIGH_QUALITY)||defined(SUN_SIMPLE)\r\n\t\tif (y < 0.0)\r\n\t\t\tcol += v_SunColor * calcSunAttenuation(-u_SunLight.direction, -ray);\r\n\t#endif\r\n\r\n\tcol = sqrt(col);//linear space convert to gamma space\r\n\tgl_FragColor=vec4(col,1.0);\r\n}\r\n\r\n";
|
||
|
||
var SkyBoxProceduralVS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\n#include \"Lighting.glsl\";\r\n\r\n#define OUTER_RADIUS 1.025\r\n#define RAYLEIGH (mix(0.0, 0.0025, pow(u_AtmosphereThickness,2.5)))// Rayleigh constant Rayleigh为夜空光和极光亮度单位\r\n#define MIE 0.0010 // Mie constant 米氏散射\r\n#define SUN_BRIGHTNESS 20.0 // Sun brightness\r\n#define MAX_SCATTER 50.0 // Maximum scattering value, to prevent math overflows on Adrenos\r\n\r\nconst float SKY_GROUND_THRESHOLD = 0.02;\r\nconst float outerRadius = OUTER_RADIUS;\r\nconst float outerRadius2 = OUTER_RADIUS*OUTER_RADIUS;\r\nconst float innerRadius = 1.0;\r\nconst float innerRadius2 = 1.0;\r\nconst float cameraHeight = 0.0001;\r\n\r\nconst float HDSundiskIntensityFactor = 15.0;\r\nconst float simpleSundiskIntensityFactor = 27.0;\r\n\r\nconst float sunScale = 400.0 * SUN_BRIGHTNESS;\r\nconst float kmESun = MIE * SUN_BRIGHTNESS;\r\nconst float km4PI = MIE * 4.0 * 3.14159265;\r\nconst float scale = 1.0 / (OUTER_RADIUS - 1.0);\r\nconst float scaleDepth = 0.25;\r\nconst float scaleOverScaleDepth = (1.0 / (OUTER_RADIUS - 1.0)) / 0.25;\r\nconst float samples = 2.0; // THIS IS UNROLLED MANUALLY, DON'T TOUCH\r\n\r\n// RGB wavelengths .35 (.62=158), .43 (.68=174), .525 (.75=190)\r\nconst vec3 c_DefaultScatteringWavelength = vec3(0.65, 0.57, 0.475);//默认散射波长\r\nconst vec3 c_VariableRangeForScatteringWavelength = vec3(0.15, 0.15, 0.15);//散射播放的可变范围\r\n\r\nattribute vec4 a_Position;\r\n\r\nuniform mat4 u_ViewProjection;\r\nuniform vec3 u_SkyTint;\r\nuniform vec3 u_GroundTint;\r\nuniform float u_Exposure;\r\nuniform float u_AtmosphereThickness;\r\nuniform DirectionLight u_SunLight;\r\n\r\nvarying vec3 v_GroundColor;\r\nvarying vec3 v_SkyColor;\r\n\r\n#ifdef SUN_HIGH_QUALITY\r\n\tvarying vec3 v_Vertex;\r\n#elif defined(SUN_SIMPLE)\r\n\tvarying vec3 v_RayDir;\r\n#else\r\n\tvarying float v_SkyGroundFactor;\r\n#endif\r\n\r\n#if defined(SUN_HIGH_QUALITY)||defined(SUN_SIMPLE)\r\n\tvarying vec3 v_SunColor;\r\n#endif\r\n\r\n// Calculates the Rayleigh phase function\r\nfloat getRayleighPhase(vec3 light, vec3 ray) \r\n{\r\n\tfloat eyeCos = dot(light, ray);\r\n\treturn 0.75 + 0.75*eyeCos*eyeCos;\r\n}\r\n\r\nfloat scaleAngle(float inCos)\r\n{\r\n\tfloat x = 1.0 - inCos;\r\n\treturn 0.25 * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25))));\r\n}\r\n\r\n\r\nvoid main () {\r\n\tgl_Position = u_ViewProjection*a_Position;\r\n\r\n\tvec3 skyTintInGammaSpace = u_SkyTint;//支持非GAMMA空间后要调整\r\n\tvec3 scatteringWavelength = mix(c_DefaultScatteringWavelength-c_VariableRangeForScatteringWavelength,c_DefaultScatteringWavelength+c_VariableRangeForScatteringWavelength,vec3(1.0) - skyTintInGammaSpace); // using Tint in sRGB+ gamma allows for more visually linear interpolation and to keep (0.5) at (128, gray in sRGB) point\r\n\tvec3 invWavelength = 1.0 / pow(scatteringWavelength, vec3(4.0));\r\n\r\n\tfloat krESun = RAYLEIGH * SUN_BRIGHTNESS;\r\n\tfloat kr4PI = RAYLEIGH * 4.0 * 3.14159265;\r\n\r\n\tvec3 cameraPos = vec3(0.0,innerRadius + cameraHeight,0.0); // The camera's current position\r\n\r\n\t// Get the ray from the camera to the vertex and its length (which is the far point of the ray passing through the atmosphere)\r\n\tvec3 eyeRay = normalize(a_Position.xyz);\r\n\r\n\tfloat far = 0.0;\r\n\tvec3 cIn, cOut;\r\n\tif (eyeRay.y >= 0.0) {// Sky\r\n\t\t// Calculate the length of the \"atmosphere\"\r\n\t\tfar = sqrt(outerRadius2 + innerRadius2 * eyeRay.y * eyeRay.y - innerRadius2) - innerRadius * eyeRay.y;\r\n\r\n\t\t// Calculate the ray's starting position, then calculate its scattering offset\r\n\t\tfloat height = innerRadius + cameraHeight;\r\n\t\tfloat depth = exp(scaleOverScaleDepth * -cameraHeight);\r\n\t\tfloat startAngle = dot(eyeRay, cameraPos) / height;\r\n\t\tfloat startOffset = depth*scaleAngle(startAngle);\r\n\r\n\t\t// Initialize the scattering loop variables\r\n\t\tfloat sampleLength = far / samples;\r\n\t\tfloat scaledLength = sampleLength * scale;\r\n\t\tvec3 sampleRay = eyeRay * sampleLength;\r\n\t\tvec3 samplePoint = cameraPos + sampleRay * 0.5;\r\n\r\n\t\tvec3 frontColor = vec3(0.0);\r\n\t\t//unrolling this manually to avoid some platform for loop slow\r\n\t\t{\r\n\t\t\tfloat height = length(samplePoint);\r\n\t\t\tfloat depth = exp(scaleOverScaleDepth * (innerRadius - height));\r\n\t\t\tfloat lightAngle = dot(-u_SunLight.direction, samplePoint) / height;\r\n\t\t\tfloat cameraAngle = dot(eyeRay, samplePoint) / height;\r\n\t\t\tfloat scatter = (startOffset + depth*(scaleAngle(lightAngle) - scaleAngle(cameraAngle)));\r\n\t\t\tvec3 attenuate = exp(-clamp(scatter, 0.0, MAX_SCATTER) * (invWavelength * kr4PI + km4PI));\r\n\r\n\t\t\tfrontColor += attenuate * (depth * scaledLength);\r\n\t\t\tsamplePoint += sampleRay;\r\n\t\t}\r\n\t\t{\r\n\t\t\tfloat height = length(samplePoint);\r\n\t\t\tfloat depth = exp(scaleOverScaleDepth * (innerRadius - height));\r\n\t\t\tfloat lightAngle = dot(-u_SunLight.direction, samplePoint) / height;\r\n\t\t\tfloat cameraAngle = dot(eyeRay, samplePoint) / height;\r\n\t\t\tfloat scatter = (startOffset + depth*(scaleAngle(lightAngle) - scaleAngle(cameraAngle)));\r\n\t\t\tvec3 attenuate = exp(-clamp(scatter, 0.0, MAX_SCATTER) * (invWavelength * kr4PI + km4PI));\r\n\r\n\t\t\tfrontColor += attenuate * (depth * scaledLength);\r\n\t\t\tsamplePoint += sampleRay;\r\n\t\t}\r\n\r\n\t\t// Finally, scale the Mie and Rayleigh colors and set up the varying variables for the pixel shader\r\n\t\tcIn = frontColor * (invWavelength * krESun);\r\n\t\tcOut = frontColor * kmESun;\r\n\t} else {// Ground\r\n\t\tfar = (-cameraHeight) / (min(-0.001, eyeRay.y));\r\n\t\tvec3 pos = cameraPos + far * eyeRay;\r\n\r\n\t\t// Calculate the ray's starting position, then calculate its scattering offset\r\n\t\tfloat depth = exp((-cameraHeight) * (1.0/scaleDepth));\r\n\t\tfloat cameraAngle = dot(-eyeRay, pos);\r\n\t\tfloat lightAngle = dot(-u_SunLight.direction, pos);\r\n\t\tfloat cameraScale = scaleAngle(cameraAngle);\r\n\t\tfloat lightScale = scaleAngle(lightAngle);\r\n\t\tfloat cameraOffset = depth*cameraScale;\r\n\t\tfloat temp = lightScale + cameraScale;\r\n\r\n\t\t// Initialize the scattering loop variables\r\n\t\tfloat sampleLength = far / samples;\r\n\t\tfloat scaledLength = sampleLength * scale;\r\n\t\tvec3 sampleRay = eyeRay * sampleLength;\r\n\t\tvec3 samplePoint = cameraPos + sampleRay * 0.5;\r\n\r\n\t\t// Now loop through the sample rays\r\n\t\tvec3 frontColor = vec3(0.0, 0.0, 0.0);\r\n\t\tvec3 attenuate;\r\n\r\n\t\t// Loop removed because we kept hitting SM2.0 temp variable limits. Doesn't affect the image too much.\r\n\t\t{\r\n\t\t\tfloat height = length(samplePoint);\r\n\t\t\tfloat depth = exp(scaleOverScaleDepth * (innerRadius - height));\r\n\t\t\tfloat scatter = depth*temp - cameraOffset;\r\n\t\t\tattenuate = exp(-clamp(scatter, 0.0, MAX_SCATTER) * (invWavelength * kr4PI + km4PI));\r\n\t\t\tfrontColor += attenuate * (depth * scaledLength);\r\n\t\t\tsamplePoint += sampleRay;\r\n\t\t}\r\n\r\n\t\tcIn = frontColor * (invWavelength * krESun + kmESun);\r\n\t\tcOut = clamp(attenuate, 0.0, 1.0);\r\n\t}\r\n\r\n\t#ifdef SUN_HIGH_QUALITY\r\n\t\tv_Vertex = -a_Position.xyz;\r\n\t#elif defined(SUN_SIMPLE) \r\n\t\tv_RayDir = -eyeRay;\r\n\t#else\r\n\t\tv_SkyGroundFactor = -eyeRay.y / SKY_GROUND_THRESHOLD;\r\n\t#endif\r\n\r\n\t// if we want to calculate color in vprog:\r\n\t// in case of linear: multiply by _Exposure in here (even in case of lerp it will be common multiplier, so we can skip mul in fshader)\r\n\tv_GroundColor = u_Exposure * (cIn + u_GroundTint*u_GroundTint * cOut);//u_GroundColor*u_GroundColor is gamma space convert to linear space\r\n\tv_SkyColor = u_Exposure * (cIn * getRayleighPhase(-u_SunLight.direction, -eyeRay));\r\n\r\n\t\r\n\t// The sun should have a stable intensity in its course in the sky. Moreover it should match the highlight of a purely specular material.\r\n\t// This matching was done using the Unity3D standard shader BRDF1 on the 5/31/2017\r\n\t// Finally we want the sun to be always bright even in LDR thus the normalization of the lightColor for low intensity.\r\n\tfloat lightColorIntensity = clamp(length(u_SunLight.color), 0.25, 1.0);\r\n\r\n\t#ifdef SUN_HIGH_QUALITY \r\n\t\tv_SunColor = HDSundiskIntensityFactor * clamp(cOut,0.0,1.0) * u_SunLight.color / lightColorIntensity;\r\n\t#elif defined(SUN_SIMPLE) \r\n\t\tv_SunColor = simpleSundiskIntensityFactor * clamp(cOut * sunScale,0.0,1.0) * u_SunLight.color / lightColorIntensity;\r\n\t#endif\r\n\tgl_Position=remapGLPositionZ(gl_Position);\r\n}\r\n";
|
||
|
||
var TrailPS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\nuniform sampler2D u_MainTexture;\r\nuniform vec4 u_MainColor;\r\n\r\nvarying vec2 v_Texcoord0;\r\nvarying vec4 v_Color;\r\n\r\nvoid main()\r\n{\r\n\tvec4 color = 2.0 * u_MainColor * v_Color;\r\n\t#ifdef MAINTEXTURE\r\n\t\tvec4 mainTextureColor = texture2D(u_MainTexture, v_Texcoord0);\r\n\t\tcolor *= mainTextureColor;\r\n\t#endif\r\n\tgl_FragColor = color;\r\n}\r\n\r\n ";
|
||
|
||
var TrailVS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n#include \"Lighting.glsl\";\r\n\r\nattribute vec3 a_Position;\r\nattribute vec3 a_OffsetVector;\r\nattribute vec4 a_Color;\r\nattribute float a_Texcoord0X;\r\nattribute float a_Texcoord0Y;\r\nattribute float a_BirthTime;\r\n\r\nuniform mat4 u_View;\r\nuniform mat4 u_Projection;\r\n\r\nuniform vec4 u_TilingOffset;\r\n\r\nuniform float u_CurTime;\r\nuniform float u_LifeTime;\r\nuniform vec4 u_WidthCurve[10];\r\nuniform int u_WidthCurveKeyLength;\r\n\r\nvarying vec2 v_Texcoord0;\r\nvarying vec4 v_Color;\r\n\r\nfloat hermiteInterpolate(float t, float outTangent, float inTangent, float duration, float value1, float value2)\r\n{\r\n\tfloat t2 = t * t;\r\n\tfloat t3 = t2 * t;\r\n\tfloat a = 2.0 * t3 - 3.0 * t2 + 1.0;\r\n\tfloat b = t3 - 2.0 * t2 + t;\r\n\tfloat c = t3 - t2;\r\n\tfloat d = -2.0 * t3 + 3.0 * t2;\r\n\treturn a * value1 + b * outTangent * duration + c * inTangent * duration + d * value2;\r\n}\r\n\r\nfloat getCurWidth(in float normalizeTime)\r\n{\r\n\tfloat width;\r\n\tif(normalizeTime == 0.0){\r\n\t\twidth=u_WidthCurve[0].w;\r\n\t}\r\n\telse if(normalizeTime >= 1.0){\r\n\t\twidth=u_WidthCurve[u_WidthCurveKeyLength - 1].w;\r\n\t}\r\n\telse{\r\n\t\tfor(int i = 0; i < 10; i ++ )\r\n\t\t{\r\n\t\t\tif(normalizeTime == u_WidthCurve[i].x){\r\n\t\t\t\twidth=u_WidthCurve[i].w;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tvec4 lastFrame = u_WidthCurve[i];\r\n\t\t\tvec4 nextFrame = u_WidthCurve[i + 1];\r\n\t\t\tif(normalizeTime > lastFrame.x && normalizeTime < nextFrame.x)\r\n\t\t\t{\r\n\t\t\t\tfloat duration = nextFrame.x - lastFrame.x;\r\n\t\t\t\tfloat t = (normalizeTime - lastFrame.x) / duration;\r\n\t\t\t\tfloat outTangent = lastFrame.z;\r\n\t\t\t\tfloat inTangent = nextFrame.y;\r\n\t\t\t\tfloat value1 = lastFrame.w;\r\n\t\t\t\tfloat value2 = nextFrame.w;\r\n\t\t\t\twidth=hermiteInterpolate(t, outTangent, inTangent, duration, value1, value2);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn width;\r\n}\t\r\n\r\nvoid main()\r\n{\r\n\tfloat normalizeTime = (u_CurTime - a_BirthTime) / u_LifeTime;\r\n\t\r\n\tv_Texcoord0 = vec2(a_Texcoord0X, 1.0 - a_Texcoord0Y) * u_TilingOffset.xy + u_TilingOffset.zw;\r\n\t\r\n\tv_Color = a_Color;\r\n\t\r\n\tvec3 cameraPos = (u_View*vec4(a_Position,1.0)).rgb;\r\n\tgl_Position = u_Projection * vec4(cameraPos+a_OffsetVector * getCurWidth(normalizeTime),1.0);\r\n\r\n\tgl_Position=remapGLPositionZ(gl_Position);\r\n}\r\n";
|
||
|
||
var UnlitPS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\n#if defined(COLOR)&&defined(ENABLEVERTEXCOLOR)\r\n\tvarying vec4 v_Color;\r\n#endif\r\n\r\n#ifdef ALBEDOTEXTURE\r\n\tuniform sampler2D u_AlbedoTexture;\r\n\tvarying vec2 v_Texcoord0;\r\n#endif\r\n\r\nuniform vec4 u_AlbedoColor;\r\n\r\n#ifdef ALPHATEST\r\n\tuniform float u_AlphaTestValue;\r\n#endif\r\n\r\n#ifdef FOG\r\n\tuniform float u_FogStart;\r\n\tuniform float u_FogRange;\r\n\t#ifdef ADDTIVEFOG\r\n\t#else\r\n\t\tuniform vec3 u_FogColor;\r\n\t#endif\r\n#endif\r\n\r\nvoid main()\r\n{\r\n\tvec4 color = u_AlbedoColor;\r\n\t#ifdef ALBEDOTEXTURE\r\n\t\tcolor *= texture2D(u_AlbedoTexture, v_Texcoord0);\r\n\t#endif\r\n\t#if defined(COLOR)&&defined(ENABLEVERTEXCOLOR)\r\n\t\tcolor *= v_Color;\r\n\t#endif\r\n\t\r\n\t#ifdef ALPHATEST\r\n\t\tif(color.a < u_AlphaTestValue)\r\n\t\t\tdiscard;\r\n\t#endif\r\n\t\r\n\tgl_FragColor = color;\r\n\t\r\n\t#ifdef FOG\r\n\t\tfloat lerpFact = clamp((1.0 / gl_FragCoord.w - u_FogStart) / u_FogRange, 0.0, 1.0);\r\n\t\t#ifdef ADDTIVEFOG\r\n\t\t\tgl_FragColor.rgb = mix(gl_FragColor.rgb, vec3(0.0), lerpFact);\r\n\t\t#else\r\n\t\t\tgl_FragColor.rgb = mix(gl_FragColor.rgb, u_FogColor, lerpFact);\r\n\t\t#endif\r\n\t#endif\r\n\t\r\n}\r\n\r\n";
|
||
|
||
var UnlitVS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n#include \"Lighting.glsl\";\r\n#include \"LayaUtile.glsl\";\r\n\r\nattribute vec4 a_Position;\r\n\r\nattribute vec2 a_Texcoord0;\r\n\r\n#ifdef GPU_INSTANCE\r\n\tuniform mat4 u_ViewProjection;\r\n\tattribute mat4 a_WorldMat;\r\n#else\r\n\tuniform mat4 u_MvpMatrix;\r\n#endif\r\n\r\nattribute vec4 a_Color;\r\nvarying vec4 v_Color;\r\nvarying vec2 v_Texcoord0;\r\n\r\nuniform vec4 u_TilingOffset;\r\n\r\n#ifdef BONE\r\n\tconst int c_MaxBoneCount = 24;\r\n\tattribute vec4 a_BoneIndices;\r\n\tattribute vec4 a_BoneWeights;\r\n\tuniform mat4 u_Bones[c_MaxBoneCount];\r\n#endif\r\n\r\nvoid main() {\r\n\tvec4 position;\r\n\t#ifdef BONE\r\n\t\tmat4 skinTransform;\r\n\t \t#ifdef SIMPLEBONE\r\n\t\t\tfloat currentPixelPos;\r\n\t\t\t#ifdef GPU_INSTANCE\r\n\t\t\t\tcurrentPixelPos = a_SimpleTextureParams.x+a_SimpleTextureParams.y;\r\n\t\t\t#else\r\n\t\t\t\tcurrentPixelPos = u_SimpleAnimatorParams.x+u_SimpleAnimatorParams.y;\r\n\t\t\t#endif\r\n\t\t\tfloat offset = 1.0/u_SimpleAnimatorTextureSize;\r\n\t\t\tskinTransform = loadMatFromTexture(currentPixelPos,int(a_BoneIndices.x),offset) * a_BoneWeights.x;\r\n\t\t\tskinTransform += loadMatFromTexture(currentPixelPos,int(a_BoneIndices.y),offset) * a_BoneWeights.y;\r\n\t\t\tskinTransform += loadMatFromTexture(currentPixelPos,int(a_BoneIndices.z),offset) * a_BoneWeights.z;\r\n\t\t\tskinTransform += loadMatFromTexture(currentPixelPos,int(a_BoneIndices.w),offset) * a_BoneWeights.w;\r\n\t\t#else\r\n\t\t\tskinTransform = u_Bones[int(a_BoneIndices.x)] * a_BoneWeights.x;\r\n\t\t\tskinTransform += u_Bones[int(a_BoneIndices.y)] * a_BoneWeights.y;\r\n\t\t\tskinTransform += u_Bones[int(a_BoneIndices.z)] * a_BoneWeights.z;\r\n\t\t\tskinTransform += u_Bones[int(a_BoneIndices.w)] * a_BoneWeights.w;\r\n\t\t#endif\r\n\t\tposition=skinTransform*a_Position;\r\n\t #else\r\n\t\tposition=a_Position;\r\n\t#endif\r\n\t#ifdef GPU_INSTANCE\r\n\t\tgl_Position =u_ViewProjection * a_WorldMat * position;\r\n\t#else\r\n\t\tgl_Position = u_MvpMatrix * position;\r\n\t#endif\r\n\r\n\tv_Texcoord0=TransformUV(a_Texcoord0,u_TilingOffset);\r\n\r\n\t#if defined(COLOR)&&defined(ENABLEVERTEXCOLOR)\r\n\t\tv_Color = a_Color;\r\n\t#endif\r\n\tgl_Position=remapGLPositionZ(gl_Position);\r\n}";
|
||
|
||
var WaterPrimaryPS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\n#ifdef MAINTEXTURE\r\n\tuniform sampler2D u_MainTexture;\r\n#endif\r\n\r\n#ifdef NORMALTEXTURE\r\n\tuniform sampler2D u_NormalTexture;\r\n#endif\r\n\r\nuniform vec4 u_HorizonColor;\r\n\r\nvarying vec3 v_Normal;\r\nvarying vec3 v_Tangent;\r\nvarying vec3 v_Binormal;\r\nvarying vec3 v_ViewDir;\r\nvarying vec2 v_Texcoord0;\r\nvarying vec2 v_Texcoord1;\r\n\r\n\r\n#include \"Lighting.glsl\"\r\n\r\n\r\n\r\nvec3 NormalSampleToWorldSpace(vec4 normalMapSample) {\r\n\tvec3 normalT;\r\n\tnormalT.x = 2.0 * normalMapSample.x - 1.0;\r\n\tnormalT.y = 1.0 - 2.0 * normalMapSample.y;\r\n\tnormalT.z = sqrt(1.0 - clamp(dot(normalT.xy, normalT.xy), 0.0, 1.0));\r\n\r\n\tvec3 bumpedNormal = normalize(normalT);\r\n\r\n\treturn bumpedNormal;\r\n}\r\n\r\n\r\nvoid main()\r\n{\r\n\tvec4 bumpColor1 = texture2D(u_NormalTexture, v_Texcoord0);\r\n\tvec4 bumpColor2 = texture2D(u_NormalTexture, v_Texcoord1);\r\n\r\n\tvec3 normal1 = NormalSampleToWorldSpace(bumpColor1);\r\n\tvec3 normal2 = NormalSampleToWorldSpace(bumpColor2);\r\n\t\r\n\tvec3 normal = normalize((normal1 + normal2) * 0.5);\r\n\tvec3 viewDir = normalize(v_ViewDir);\r\n\tfloat fresnel = dot(viewDir, normal);\r\n\t\r\n\tvec4 waterColor = texture2D(u_MainTexture, vec2(fresnel, fresnel));\r\n\t\r\n\tvec4 color;\r\n\tcolor.rgb = mix(waterColor.rgb, u_HorizonColor.rgb, vec3(waterColor.a));\r\n\tcolor.a = u_HorizonColor.a;\r\n\t\r\n\tgl_FragColor = color;\r\n}\r\n\r\n\r\n";
|
||
|
||
var WaterPrimaryVS = "#include \"Lighting.glsl\";\r\n\r\nattribute vec4 a_Position;\r\nattribute vec3 a_Normal;\r\nattribute vec4 a_Tangent0;\r\n\r\nuniform mat4 u_MvpMatrix;\r\nuniform mat4 u_WorldMat;\r\nuniform vec3 u_CameraPos;\r\nuniform float u_WaveScale;\r\nuniform vec4 u_WaveSpeed;\r\nuniform float u_Time;\r\n\r\nvarying vec3 v_Normal;\r\nvarying vec3 v_Tangent;\r\nvarying vec3 v_Binormal;\r\nvarying vec3 v_ViewDir;\r\nvarying vec2 v_Texcoord0;\r\nvarying vec2 v_Texcoord1;\r\n\r\nvoid main()\r\n{\r\n\tvec4 positionWorld = u_WorldMat * a_Position;\r\n\tvec4 position = u_MvpMatrix * a_Position;\r\n\t\r\n\tvec4 temp = vec4(positionWorld.x, positionWorld.z, positionWorld.x, positionWorld.z) * u_WaveScale + u_WaveSpeed * u_WaveScale * u_Time;\r\n\t\r\n\tv_Texcoord0 = temp.xy * vec2(0.4, 0.45);\r\n\tv_Texcoord1 = temp.wz;\r\n\t\r\n\tmat3 worldMat = mat3(u_WorldMat);\r\n\tv_Normal = worldMat * a_Normal;\r\n\tv_Tangent = worldMat * a_Tangent0.xyz;\r\n\tv_Binormal = cross(v_Normal, v_Tangent) * a_Tangent0.w;\r\n\t\r\n\tv_ViewDir = u_CameraPos - positionWorld.xyz;\r\n\tgl_Position = position;\r\n\tgl_Position=remapGLPositionZ(gl_Position);\r\n}";
|
||
|
||
var DepthNormalUtil = "#define SAMPLE_DEPTH_TEXTURE(textureName,coord2) (texture2D(textureName,coord2).r)\r\n//此方法库用来压缩解析深度贴图,法线深度贴图\r\n\r\n/*camera 传入的Texture以及*/\r\nuniform sampler2D u_CameraDepthTexture;\r\nuniform vec4 u_ZBufferParams;\r\nuniform sampler2D u_CameraDepthNormalsTexture;\r\n\r\n// Encoding/decoding view space normals into 2D 0..1 vector\r\nvec2 EncodeViewNormalStereo( vec3 n )\r\n{\r\n n.z = abs(n.z);\r\n float kScale = 1.7777;\r\n vec2 enc;\r\n enc = n.xy / (n.z+1.0);\r\n enc /= kScale;\r\n enc = enc*0.5+0.5;\r\n return enc;\r\n}\r\n\r\nvec3 DecodeViewNormalStereo( vec4 enc4 )\r\n{\r\n float kScale = 1.7777;\r\n vec3 nn = enc4.xyz*vec3(2.0*kScale,2.0*kScale,0.0) + vec3(-kScale,-kScale,1.0);\r\n float g = 2.0 / dot(nn.xyz,nn.xyz);\r\n vec3 n;\r\n n.xy = g*nn.xy;\r\n n.z = g-1.0;\r\n return n;\r\n}\r\n\r\n\r\n// Encoding/decoding [0..1) floats into 8 bit/channel RG. Note that 1.0 will not be encoded properly.\r\nvec2 EncodeFloatRG( float v )\r\n{\r\n vec2 kEncodeMul = vec2(1.0, 255.0);\r\n float kEncodeBit = 1.0/255.0;\r\n vec2 enc = kEncodeMul * v;\r\n enc = fract(enc);\r\n enc.x -= enc.y * kEncodeBit;\r\n return enc;\r\n}\r\n\r\n\r\n\r\nfloat DecodeFloatRG( vec2 enc )\r\n{\r\n vec2 kDecodeDot = vec2(1.0, 1.0/255.0);\r\n return dot( enc, kDecodeDot );\r\n}\r\n\r\nvec4 EncodeDepthNormal(float depth,vec3 normals){\r\n\tvec4 encode;\r\n\tencode.xy = EncodeViewNormalStereo(normals);\r\n\tencode.zw = EncodeFloatRG(depth);\r\n return encode;\r\n}\r\n\r\nvoid DecodeDepthNormal( vec4 enc, out float depth, out vec3 normal )\r\n{\r\n depth = DecodeFloatRG (enc.zw);\r\n normal = DecodeViewNormalStereo (enc);\r\n}\r\n\r\n\r\n\r\nvec4 depthNormalsFragment(vec4 depthNormal)\r\n{\r\n return EncodeDepthNormal(depthNormal.w,depthNormal.xyz);\r\n}\r\n\r\n\r\n// Z buffer to linear 0..1 depth\r\nfloat Linear01Depth(float z,vec4 zbufferParams)\r\n{\r\n return 1.0 / (zbufferParams.x * z + zbufferParams.y);\r\n}\r\n// Z buffer to linear depth\r\nfloat LinearEyeDepth(float z,vec4 zbufferParams)\r\n{\r\n return 1.0 / (zbufferParams.z * z + zbufferParams.w);\r\n}\r\n";
|
||
|
||
class ShaderInit3D {
|
||
constructor() {
|
||
}
|
||
static __init__() {
|
||
Shader3D.SHADERDEFINE_LEGACYSINGALLIGHTING = Shader3D.getDefineByName("LEGACYSINGLELIGHTING");
|
||
Shader3D.SHADERDEFINE_GRAPHICS_API_GLES2 = Shader3D.getDefineByName("GRAPHICS_API_GLES2");
|
||
Shader3D.SHADERDEFINE_GRAPHICS_API_GLES3 = Shader3D.getDefineByName("GRAPHICS_API_GLES3");
|
||
Shader3D.addInclude("Lighting.glsl", LightingGLSL);
|
||
Shader3D.addInclude("ShadowSampleTent.glsl", ShadowSampleTentGLSL);
|
||
Shader3D.addInclude("GlobalIllumination.glsl", GlobalIllumination);
|
||
Shader3D.addInclude("Shadow.glsl", ShadowGLSL);
|
||
Shader3D.addInclude("ShadowCasterVS.glsl", ShadowCasterVSGLSL);
|
||
Shader3D.addInclude("ShadowCasterFS.glsl", ShadowCasterFSGLSL);
|
||
Shader3D.addInclude("Colors.glsl", ColorsGLSL);
|
||
Shader3D.addInclude("Sampling.glsl", SamplingGLSL);
|
||
Shader3D.addInclude("StdLib.glsl", StdLibGLSL);
|
||
Shader3D.addInclude("PBRVSInput.glsl", PBRVSInput);
|
||
Shader3D.addInclude("PBRFSInput.glsl", PBRFSInput);
|
||
Shader3D.addInclude("LayaPBRBRDF.glsl", LayaPBRBRDF);
|
||
Shader3D.addInclude("PBRCore.glsl", PBRCore);
|
||
Shader3D.addInclude("PBRVertex.glsl", PBRVertex);
|
||
Shader3D.addInclude("LayaUtile.glsl", LayaUtile);
|
||
Shader3D.addInclude("DepthNormalUtil.glsl", DepthNormalUtil);
|
||
var attributeMap = {
|
||
'a_Position': VertexMesh.MESH_POSITION0,
|
||
'a_Color': VertexMesh.MESH_COLOR0,
|
||
'a_Normal': VertexMesh.MESH_NORMAL0,
|
||
'a_Texcoord0': VertexMesh.MESH_TEXTURECOORDINATE0,
|
||
'a_Texcoord1': VertexMesh.MESH_TEXTURECOORDINATE1,
|
||
'a_BoneWeights': VertexMesh.MESH_BLENDWEIGHT0,
|
||
'a_BoneIndices': VertexMesh.MESH_BLENDINDICES0,
|
||
'a_Tangent0': VertexMesh.MESH_TANGENT0,
|
||
'a_WorldMat': VertexMesh.MESH_WORLDMATRIX_ROW0,
|
||
'a_SimpleTextureParams': VertexMesh.MESH_SIMPLEANIMATOR
|
||
};
|
||
var uniformMap = {
|
||
'u_Bones': Shader3D.PERIOD_CUSTOM,
|
||
'u_DiffuseTexture': Shader3D.PERIOD_MATERIAL,
|
||
'u_SpecularTexture': Shader3D.PERIOD_MATERIAL,
|
||
'u_NormalTexture': Shader3D.PERIOD_MATERIAL,
|
||
'u_AlphaTestValue': Shader3D.PERIOD_MATERIAL,
|
||
'u_DiffuseColor': Shader3D.PERIOD_MATERIAL,
|
||
'u_AlbedoIntensity': Shader3D.PERIOD_MATERIAL,
|
||
'u_MaterialSpecular': Shader3D.PERIOD_MATERIAL,
|
||
'u_Shininess': Shader3D.PERIOD_MATERIAL,
|
||
'u_TilingOffset': Shader3D.PERIOD_MATERIAL,
|
||
'u_TransmissionRate': Shader3D.PERIOD_MATERIAL,
|
||
'u_BackDiffuse': Shader3D.PERIOD_MATERIAL,
|
||
'u_BackScale': Shader3D.PERIOD_MATERIAL,
|
||
'u_ThinknessTexture': Shader3D.PERIOD_MATERIAL,
|
||
'u_TransmissionColor': Shader3D.PERIOD_MATERIAL,
|
||
'u_WorldMat': Shader3D.PERIOD_SPRITE,
|
||
'u_MvpMatrix': Shader3D.PERIOD_SPRITE,
|
||
'u_LightmapScaleOffset': Shader3D.PERIOD_SPRITE,
|
||
'u_LightMap': Shader3D.PERIOD_SPRITE,
|
||
'u_LightMapDirection': Shader3D.PERIOD_SPRITE,
|
||
'u_SimpleAnimatorTexture': Shader3D.PERIOD_SPRITE,
|
||
'u_SimpleAnimatorParams': Shader3D.PERIOD_SPRITE,
|
||
'u_SimpleAnimatorTextureSize': Shader3D.PERIOD_SPRITE,
|
||
'u_CameraPos': Shader3D.PERIOD_CAMERA,
|
||
'u_Viewport': Shader3D.PERIOD_CAMERA,
|
||
'u_ProjectionParams': Shader3D.PERIOD_CAMERA,
|
||
'u_View': Shader3D.PERIOD_CAMERA,
|
||
'u_ViewProjection': Shader3D.PERIOD_CAMERA,
|
||
'u_ReflectTexture': Shader3D.PERIOD_SCENE,
|
||
'u_FogStart': Shader3D.PERIOD_SCENE,
|
||
'u_FogRange': Shader3D.PERIOD_SCENE,
|
||
'u_FogColor': Shader3D.PERIOD_SCENE,
|
||
'u_DirationLightCount': Shader3D.PERIOD_SCENE,
|
||
'u_LightBuffer': Shader3D.PERIOD_SCENE,
|
||
'u_LightClusterBuffer': Shader3D.PERIOD_SCENE,
|
||
'u_AmbientColor': Shader3D.PERIOD_SCENE,
|
||
'u_ShadowBias': Shader3D.PERIOD_SCENE,
|
||
'u_ShadowLightDirection': Shader3D.PERIOD_SCENE,
|
||
'u_ShadowMap': Shader3D.PERIOD_SCENE,
|
||
'u_ShadowParams': Shader3D.PERIOD_SCENE,
|
||
'u_ShadowSplitSpheres': Shader3D.PERIOD_SCENE,
|
||
'u_ShadowMatrices': Shader3D.PERIOD_SCENE,
|
||
'u_ShadowMapSize': Shader3D.PERIOD_SCENE,
|
||
'u_SpotShadowMap': Shader3D.PERIOD_SCENE,
|
||
'u_SpotViewProjectMatrix': Shader3D.PERIOD_SCENE,
|
||
'u_ShadowLightPosition': Shader3D.PERIOD_SCENE,
|
||
'u_AmbientSHAr': Shader3D.PERIOD_SCENE,
|
||
'u_AmbientSHAg': Shader3D.PERIOD_SCENE,
|
||
'u_AmbientSHAb': Shader3D.PERIOD_SCENE,
|
||
'u_AmbientSHBr': Shader3D.PERIOD_SCENE,
|
||
'u_AmbientSHBg': Shader3D.PERIOD_SCENE,
|
||
'u_AmbientSHBb': Shader3D.PERIOD_SCENE,
|
||
'u_AmbientSHC': Shader3D.PERIOD_SCENE,
|
||
'u_DirectionLight.color': Shader3D.PERIOD_SCENE,
|
||
'u_DirectionLight.direction': Shader3D.PERIOD_SCENE,
|
||
'u_PointLight.position': Shader3D.PERIOD_SCENE,
|
||
'u_PointLight.range': Shader3D.PERIOD_SCENE,
|
||
'u_PointLight.color': Shader3D.PERIOD_SCENE,
|
||
'u_SpotLight.position': Shader3D.PERIOD_SCENE,
|
||
'u_SpotLight.direction': Shader3D.PERIOD_SCENE,
|
||
'u_SpotLight.range': Shader3D.PERIOD_SCENE,
|
||
'u_SpotLight.spot': Shader3D.PERIOD_SCENE,
|
||
'u_SpotLight.color': Shader3D.PERIOD_SCENE
|
||
};
|
||
var stateMap = {
|
||
's_Cull': Shader3D.RENDER_STATE_CULL,
|
||
's_Blend': Shader3D.RENDER_STATE_BLEND,
|
||
's_BlendSrc': Shader3D.RENDER_STATE_BLEND_SRC,
|
||
's_BlendDst': Shader3D.RENDER_STATE_BLEND_DST,
|
||
's_DepthTest': Shader3D.RENDER_STATE_DEPTH_TEST,
|
||
's_DepthWrite': Shader3D.RENDER_STATE_DEPTH_WRITE
|
||
};
|
||
var shader = Shader3D.add("BLINNPHONG", null, null, true);
|
||
var subShader = new SubShader(attributeMap, uniformMap);
|
||
shader.addSubShader(subShader);
|
||
subShader.addShaderPass(MeshBlinnPhongVS, MeshBlinnPhongPS, stateMap, "Forward");
|
||
var shaderPass = subShader.addShaderPass(MeshBlinnPhongShadowCasterVS, MeshBlinnPhongShadowCasterPS, stateMap, "ShadowCaster");
|
||
shaderPass = subShader.addShaderPass(DepthNormalsTextureVS, DepthNormalsTextureFS, stateMap, "DepthNormal");
|
||
attributeMap = {
|
||
'a_Position': VertexMesh.MESH_POSITION0,
|
||
'a_Color': VertexMesh.MESH_COLOR0
|
||
};
|
||
uniformMap = {
|
||
'u_MvpMatrix': Shader3D.PERIOD_SPRITE,
|
||
'u_Color': Shader3D.PERIOD_MATERIAL
|
||
};
|
||
stateMap = {
|
||
's_Cull': Shader3D.RENDER_STATE_CULL,
|
||
's_Blend': Shader3D.RENDER_STATE_BLEND,
|
||
's_BlendSrc': Shader3D.RENDER_STATE_BLEND_SRC,
|
||
's_BlendDst': Shader3D.RENDER_STATE_BLEND_DST,
|
||
's_DepthTest': Shader3D.RENDER_STATE_DEPTH_TEST,
|
||
's_DepthWrite': Shader3D.RENDER_STATE_DEPTH_WRITE
|
||
};
|
||
shader = Shader3D.add("LineShader");
|
||
subShader = new SubShader(attributeMap, uniformMap);
|
||
shader.addSubShader(subShader);
|
||
subShader.addShaderPass(lineVS, linePS, stateMap);
|
||
attributeMap = {
|
||
'a_Position': VertexMesh.MESH_POSITION0,
|
||
'a_Color': VertexMesh.MESH_COLOR0,
|
||
'a_Texcoord0': VertexMesh.MESH_TEXTURECOORDINATE0,
|
||
'a_BoneWeights': VertexMesh.MESH_BLENDWEIGHT0,
|
||
'a_BoneIndices': VertexMesh.MESH_BLENDINDICES0,
|
||
'a_WorldMat': VertexMesh.MESH_WORLDMATRIX_ROW0,
|
||
'a_SimpleTextureParams': VertexMesh.MESH_SIMPLEANIMATOR
|
||
};
|
||
uniformMap = {
|
||
'u_Bones': Shader3D.PERIOD_CUSTOM,
|
||
'u_AlbedoTexture': Shader3D.PERIOD_MATERIAL,
|
||
'u_AlbedoColor': Shader3D.PERIOD_MATERIAL,
|
||
'u_TilingOffset': Shader3D.PERIOD_MATERIAL,
|
||
'u_AlphaTestValue': Shader3D.PERIOD_MATERIAL,
|
||
'u_MvpMatrix': Shader3D.PERIOD_SPRITE,
|
||
'u_ViewProjection': Shader3D.PERIOD_CAMERA,
|
||
'u_SimpleAnimatorTexture': Shader3D.PERIOD_SPRITE,
|
||
'u_SimpleAnimatorParams': Shader3D.PERIOD_SPRITE,
|
||
'u_SimpleAnimatorTextureSize': Shader3D.PERIOD_SPRITE,
|
||
'u_FogStart': Shader3D.PERIOD_SCENE,
|
||
'u_FogRange': Shader3D.PERIOD_SCENE,
|
||
'u_FogColor': Shader3D.PERIOD_SCENE
|
||
};
|
||
stateMap = {
|
||
's_Cull': Shader3D.RENDER_STATE_CULL,
|
||
's_Blend': Shader3D.RENDER_STATE_BLEND,
|
||
's_BlendSrc': Shader3D.RENDER_STATE_BLEND_SRC,
|
||
's_BlendDst': Shader3D.RENDER_STATE_BLEND_DST,
|
||
's_DepthTest': Shader3D.RENDER_STATE_DEPTH_TEST,
|
||
's_DepthWrite': Shader3D.RENDER_STATE_DEPTH_WRITE
|
||
};
|
||
shader = Shader3D.add("Unlit", null, null, true);
|
||
subShader = new SubShader(attributeMap, uniformMap);
|
||
shader.addSubShader(subShader);
|
||
subShader.addShaderPass(UnlitVS, UnlitPS, stateMap);
|
||
attributeMap = {
|
||
'a_Position': VertexMesh.MESH_POSITION0,
|
||
'a_Texcoord0': VertexMesh.MESH_TEXTURECOORDINATE0,
|
||
'a_BoneWeights': VertexMesh.MESH_BLENDWEIGHT0,
|
||
'a_BoneIndices': VertexMesh.MESH_BLENDINDICES0,
|
||
'a_WorldMat': VertexMesh.MESH_WORLDMATRIX_ROW0,
|
||
'a_SimpleTextureParams': VertexMesh.MESH_SIMPLEANIMATOR
|
||
};
|
||
uniformMap = {
|
||
'u_Bones': Shader3D.PERIOD_CUSTOM,
|
||
'u_AlbedoTexture': Shader3D.PERIOD_MATERIAL,
|
||
'u_AlbedoColor': Shader3D.PERIOD_MATERIAL,
|
||
'u_TilingOffset': Shader3D.PERIOD_MATERIAL,
|
||
'u_AlphaTestValue': Shader3D.PERIOD_MATERIAL,
|
||
'u_ViewProjection': Shader3D.PERIOD_CAMERA,
|
||
'u_MvpMatrix': Shader3D.PERIOD_SPRITE,
|
||
'u_SimpleAnimatorTexture': Shader3D.PERIOD_SPRITE,
|
||
'u_SimpleAnimatorParams': Shader3D.PERIOD_SPRITE,
|
||
'u_SimpleAnimatorTextureSize': Shader3D.PERIOD_SPRITE,
|
||
'u_FogStart': Shader3D.PERIOD_SCENE,
|
||
'u_FogRange': Shader3D.PERIOD_SCENE,
|
||
'u_FogColor': Shader3D.PERIOD_SCENE
|
||
};
|
||
stateMap = {
|
||
's_Cull': Shader3D.RENDER_STATE_CULL,
|
||
's_Blend': Shader3D.RENDER_STATE_BLEND,
|
||
's_BlendSrc': Shader3D.RENDER_STATE_BLEND_SRC,
|
||
's_BlendDst': Shader3D.RENDER_STATE_BLEND_DST,
|
||
's_DepthTest': Shader3D.RENDER_STATE_DEPTH_TEST,
|
||
's_DepthWrite': Shader3D.RENDER_STATE_DEPTH_WRITE
|
||
};
|
||
shader = Shader3D.add("Effect", null, null, true);
|
||
subShader = new SubShader(attributeMap, uniformMap);
|
||
shader.addSubShader(subShader);
|
||
subShader.addShaderPass(EffectVS, EffectPS, stateMap);
|
||
attributeMap = {
|
||
'a_CornerTextureCoordinate': VertexShuriKenParticle.PARTICLE_CORNERTEXTURECOORDINATE0,
|
||
'a_MeshPosition': VertexShuriKenParticle.PARTICLE_POSITION0,
|
||
'a_MeshColor': VertexShuriKenParticle.PARTICLE_COLOR0,
|
||
'a_MeshTextureCoordinate': VertexShuriKenParticle.PARTICLE_TEXTURECOORDINATE0,
|
||
'a_ShapePositionStartLifeTime': VertexShuriKenParticle.PARTICLE_SHAPEPOSITIONSTARTLIFETIME,
|
||
'a_DirectionTime': VertexShuriKenParticle.PARTICLE_DIRECTIONTIME,
|
||
'a_StartColor': VertexShuriKenParticle.PARTICLE_STARTCOLOR0,
|
||
'a_EndColor': VertexShuriKenParticle.PARTICLE_ENDCOLOR0,
|
||
'a_StartSize': VertexShuriKenParticle.PARTICLE_STARTSIZE,
|
||
'a_StartRotation0': VertexShuriKenParticle.PARTICLE_STARTROTATION,
|
||
'a_StartSpeed': VertexShuriKenParticle.PARTICLE_STARTSPEED,
|
||
'a_Random0': VertexShuriKenParticle.PARTICLE_RANDOM0,
|
||
'a_Random1': VertexShuriKenParticle.PARTICLE_RANDOM1,
|
||
'a_SimulationWorldPostion': VertexShuriKenParticle.PARTICLE_SIMULATIONWORLDPOSTION,
|
||
'a_SimulationWorldRotation': VertexShuriKenParticle.PARTICLE_SIMULATIONWORLDROTATION
|
||
};
|
||
uniformMap = {
|
||
'u_Tintcolor': Shader3D.PERIOD_MATERIAL,
|
||
'u_TilingOffset': Shader3D.PERIOD_MATERIAL,
|
||
'u_texture': Shader3D.PERIOD_MATERIAL,
|
||
'u_WorldPosition': Shader3D.PERIOD_SPRITE,
|
||
'u_WorldRotation': Shader3D.PERIOD_SPRITE,
|
||
'u_PositionScale': Shader3D.PERIOD_SPRITE,
|
||
'u_SizeScale': Shader3D.PERIOD_SPRITE,
|
||
'u_ScalingMode': Shader3D.PERIOD_SPRITE,
|
||
'u_Gravity': Shader3D.PERIOD_SPRITE,
|
||
'u_ThreeDStartRotation': Shader3D.PERIOD_SPRITE,
|
||
'u_StretchedBillboardLengthScale': Shader3D.PERIOD_SPRITE,
|
||
'u_StretchedBillboardSpeedScale': Shader3D.PERIOD_SPRITE,
|
||
'u_SimulationSpace': Shader3D.PERIOD_SPRITE,
|
||
'u_CurrentTime': Shader3D.PERIOD_SPRITE,
|
||
'u_ColorOverLifeGradientAlphas': Shader3D.PERIOD_SPRITE,
|
||
'u_ColorOverLifeGradientColors': Shader3D.PERIOD_SPRITE,
|
||
'u_MaxColorOverLifeGradientAlphas': Shader3D.PERIOD_SPRITE,
|
||
'u_MaxColorOverLifeGradientColors': Shader3D.PERIOD_SPRITE,
|
||
'u_VOLVelocityConst': Shader3D.PERIOD_SPRITE,
|
||
'u_VOLVelocityGradientX': Shader3D.PERIOD_SPRITE,
|
||
'u_VOLVelocityGradientY': Shader3D.PERIOD_SPRITE,
|
||
'u_VOLVelocityGradientZ': Shader3D.PERIOD_SPRITE,
|
||
'u_VOLVelocityConstMax': Shader3D.PERIOD_SPRITE,
|
||
'u_VOLVelocityGradientMaxX': Shader3D.PERIOD_SPRITE,
|
||
'u_VOLVelocityGradientMaxY': Shader3D.PERIOD_SPRITE,
|
||
'u_VOLVelocityGradientMaxZ': Shader3D.PERIOD_SPRITE,
|
||
'u_VOLSpaceType': Shader3D.PERIOD_SPRITE,
|
||
'u_SOLSizeGradient': Shader3D.PERIOD_SPRITE,
|
||
'u_SOLSizeGradientX': Shader3D.PERIOD_SPRITE,
|
||
'u_SOLSizeGradientY': Shader3D.PERIOD_SPRITE,
|
||
'u_SOLSizeGradientZ': Shader3D.PERIOD_SPRITE,
|
||
'u_SOLSizeGradientMax': Shader3D.PERIOD_SPRITE,
|
||
'u_SOLSizeGradientMaxX': Shader3D.PERIOD_SPRITE,
|
||
'u_SOLSizeGradientMaxY': Shader3D.PERIOD_SPRITE,
|
||
'u_SOLSizeGradientMaxZ': Shader3D.PERIOD_SPRITE,
|
||
'u_ROLAngularVelocityConst': Shader3D.PERIOD_SPRITE,
|
||
'u_ROLAngularVelocityConstSeprarate': Shader3D.PERIOD_SPRITE,
|
||
'u_ROLAngularVelocityGradient': Shader3D.PERIOD_SPRITE,
|
||
'u_ROLAngularVelocityGradientX': Shader3D.PERIOD_SPRITE,
|
||
'u_ROLAngularVelocityGradientY': Shader3D.PERIOD_SPRITE,
|
||
'u_ROLAngularVelocityGradientZ': Shader3D.PERIOD_SPRITE,
|
||
'u_ROLAngularVelocityConstMax': Shader3D.PERIOD_SPRITE,
|
||
'u_ROLAngularVelocityConstMaxSeprarate': Shader3D.PERIOD_SPRITE,
|
||
'u_ROLAngularVelocityGradientMax': Shader3D.PERIOD_SPRITE,
|
||
'u_ROLAngularVelocityGradientMaxX': Shader3D.PERIOD_SPRITE,
|
||
'u_ROLAngularVelocityGradientMaxY': Shader3D.PERIOD_SPRITE,
|
||
'u_ROLAngularVelocityGradientMaxZ': Shader3D.PERIOD_SPRITE,
|
||
'u_ROLAngularVelocityGradientMaxW': Shader3D.PERIOD_SPRITE,
|
||
'u_TSACycles': Shader3D.PERIOD_SPRITE,
|
||
'u_TSASubUVLength': Shader3D.PERIOD_SPRITE,
|
||
'u_TSAGradientUVs': Shader3D.PERIOD_SPRITE,
|
||
'u_TSAMaxGradientUVs': Shader3D.PERIOD_SPRITE,
|
||
'u_CameraPos': Shader3D.PERIOD_CAMERA,
|
||
'u_CameraDirection': Shader3D.PERIOD_CAMERA,
|
||
'u_CameraUp': Shader3D.PERIOD_CAMERA,
|
||
'u_View': Shader3D.PERIOD_CAMERA,
|
||
'u_Projection': Shader3D.PERIOD_CAMERA,
|
||
'u_FogStart': Shader3D.PERIOD_SCENE,
|
||
'u_FogRange': Shader3D.PERIOD_SCENE,
|
||
'u_FogColor': Shader3D.PERIOD_SCENE
|
||
};
|
||
stateMap = {
|
||
's_Cull': Shader3D.RENDER_STATE_CULL,
|
||
's_Blend': Shader3D.RENDER_STATE_BLEND,
|
||
's_BlendSrc': Shader3D.RENDER_STATE_BLEND_SRC,
|
||
's_BlendDst': Shader3D.RENDER_STATE_BLEND_DST,
|
||
's_DepthTest': Shader3D.RENDER_STATE_DEPTH_TEST,
|
||
's_DepthWrite': Shader3D.RENDER_STATE_DEPTH_WRITE
|
||
};
|
||
shader = Shader3D.add("PARTICLESHURIKEN");
|
||
subShader = new SubShader(attributeMap, uniformMap);
|
||
shader.addSubShader(subShader);
|
||
subShader.addShaderPass(ParticleShuriKenVS, ParticleShuriKenPS, stateMap);
|
||
attributeMap = {
|
||
'a_Position': VertexMesh.MESH_POSITION0
|
||
};
|
||
uniformMap = {
|
||
'u_TintColor': Shader3D.PERIOD_MATERIAL,
|
||
'u_Exposure': Shader3D.PERIOD_MATERIAL,
|
||
'u_Rotation': Shader3D.PERIOD_MATERIAL,
|
||
'u_CubeTexture': Shader3D.PERIOD_MATERIAL,
|
||
'u_ViewProjection': Shader3D.PERIOD_CAMERA
|
||
};
|
||
shader = Shader3D.add("SkyBox");
|
||
subShader = new SubShader(attributeMap, uniformMap);
|
||
shader.addSubShader(subShader);
|
||
subShader.addShaderPass(SkyBoxVS, SkyBoxPS);
|
||
attributeMap = {
|
||
'a_Position': VertexMesh.MESH_POSITION0
|
||
};
|
||
uniformMap = {
|
||
'u_SunSize': Shader3D.PERIOD_MATERIAL,
|
||
'u_SunSizeConvergence': Shader3D.PERIOD_MATERIAL,
|
||
'u_AtmosphereThickness': Shader3D.PERIOD_MATERIAL,
|
||
'u_SkyTint': Shader3D.PERIOD_MATERIAL,
|
||
'u_GroundTint': Shader3D.PERIOD_MATERIAL,
|
||
'u_Exposure': Shader3D.PERIOD_MATERIAL,
|
||
'u_ViewProjection': Shader3D.PERIOD_CAMERA,
|
||
'u_SunLight.direction': Shader3D.PERIOD_SCENE,
|
||
'u_SunLight.color': Shader3D.PERIOD_SCENE,
|
||
};
|
||
shader = Shader3D.add("SkyBoxProcedural");
|
||
subShader = new SubShader(attributeMap, uniformMap);
|
||
shader.addSubShader(subShader);
|
||
subShader.addShaderPass(SkyBoxProceduralVS, SkyBoxProceduralPS);
|
||
attributeMap = {
|
||
'a_Position': VertexMesh.MESH_POSITION0,
|
||
'a_Normal': VertexMesh.MESH_NORMAL0,
|
||
'a_Texcoord0': VertexMesh.MESH_TEXTURECOORDINATE0
|
||
};
|
||
uniformMap = {
|
||
'u_MvpMatrix': Shader3D.PERIOD_SPRITE,
|
||
'u_WorldMat': Shader3D.PERIOD_SPRITE,
|
||
'u_CameraPos': Shader3D.PERIOD_CAMERA,
|
||
'u_Viewport': Shader3D.PERIOD_CAMERA,
|
||
'u_ProjectionParams': Shader3D.PERIOD_CAMERA,
|
||
'u_View': Shader3D.PERIOD_CAMERA,
|
||
'u_LightmapScaleOffset': Shader3D.PERIOD_SPRITE,
|
||
'u_LightMap': Shader3D.PERIOD_SPRITE,
|
||
'u_SplatAlphaTexture': Shader3D.PERIOD_MATERIAL,
|
||
'u_DiffuseTexture1': Shader3D.PERIOD_MATERIAL,
|
||
'u_DiffuseTexture2': Shader3D.PERIOD_MATERIAL,
|
||
'u_DiffuseTexture3': Shader3D.PERIOD_MATERIAL,
|
||
'u_DiffuseTexture4': Shader3D.PERIOD_MATERIAL,
|
||
'u_DiffuseTexture5': Shader3D.PERIOD_MATERIAL,
|
||
'u_DiffuseScaleOffset1': Shader3D.PERIOD_MATERIAL,
|
||
'u_DiffuseScaleOffset2': Shader3D.PERIOD_MATERIAL,
|
||
'u_DiffuseScaleOffset3': Shader3D.PERIOD_MATERIAL,
|
||
'u_DiffuseScaleOffset4': Shader3D.PERIOD_MATERIAL,
|
||
'u_DiffuseScaleOffset5': Shader3D.PERIOD_MATERIAL,
|
||
'u_FogStart': Shader3D.PERIOD_SCENE,
|
||
'u_FogRange': Shader3D.PERIOD_SCENE,
|
||
'u_FogColor': Shader3D.PERIOD_SCENE,
|
||
'u_DirationLightCount': Shader3D.PERIOD_SCENE,
|
||
'u_LightBuffer': Shader3D.PERIOD_SCENE,
|
||
'u_LightClusterBuffer': Shader3D.PERIOD_SCENE,
|
||
'u_AmbientColor': Shader3D.PERIOD_SCENE,
|
||
'u_ShadowMap': Shader3D.PERIOD_SCENE,
|
||
'u_shadowMap2': Shader3D.PERIOD_SCENE,
|
||
'u_shadowMap3': Shader3D.PERIOD_SCENE,
|
||
'u_ShadowSplitSpheres': Shader3D.PERIOD_SCENE,
|
||
'u_ShadowMatrices': Shader3D.PERIOD_SCENE,
|
||
'u_ShadowMapSize': Shader3D.PERIOD_SCENE,
|
||
'u_DirectionLight.color': Shader3D.PERIOD_SCENE,
|
||
'u_DirectionLight.direction': Shader3D.PERIOD_SCENE,
|
||
'u_PointLight.position': Shader3D.PERIOD_SCENE,
|
||
'u_PointLight.range': Shader3D.PERIOD_SCENE,
|
||
'u_PointLight.color': Shader3D.PERIOD_SCENE,
|
||
'u_SpotLight.position': Shader3D.PERIOD_SCENE,
|
||
'u_SpotLight.direction': Shader3D.PERIOD_SCENE,
|
||
'u_SpotLight.range': Shader3D.PERIOD_SCENE,
|
||
'u_SpotLight.spot': Shader3D.PERIOD_SCENE,
|
||
'u_SpotLight.color': Shader3D.PERIOD_SCENE
|
||
};
|
||
stateMap = {
|
||
's_Cull': Shader3D.RENDER_STATE_CULL,
|
||
's_Blend': Shader3D.RENDER_STATE_BLEND,
|
||
's_BlendSrc': Shader3D.RENDER_STATE_BLEND_SRC,
|
||
's_BlendDst': Shader3D.RENDER_STATE_BLEND_DST,
|
||
's_DepthTest': Shader3D.RENDER_STATE_DEPTH_TEST,
|
||
's_DepthWrite': Shader3D.RENDER_STATE_DEPTH_WRITE
|
||
};
|
||
shader = Shader3D.add("ExtendTerrain");
|
||
subShader = new SubShader(attributeMap, uniformMap);
|
||
shader.addSubShader(subShader);
|
||
subShader.addShaderPass(extendTerrainVS, extendTerrainPS, stateMap);
|
||
attributeMap = {
|
||
'a_Position': VertexTrail.TRAIL_POSITION0,
|
||
'a_OffsetVector': VertexTrail.TRAIL_OFFSETVECTOR,
|
||
'a_Texcoord0X': VertexTrail.TRAIL_TEXTURECOORDINATE0X,
|
||
'a_Texcoord0Y': VertexTrail.TRAIL_TEXTURECOORDINATE0Y,
|
||
'a_BirthTime': VertexTrail.TRAIL_TIME0,
|
||
'a_Color': VertexTrail.TRAIL_COLOR
|
||
};
|
||
uniformMap = {
|
||
'u_MvpMatrix': Shader3D.PERIOD_SPRITE,
|
||
'u_View': Shader3D.PERIOD_CAMERA,
|
||
'u_Projection': Shader3D.PERIOD_CAMERA,
|
||
'u_TilingOffset': Shader3D.PERIOD_MATERIAL,
|
||
'u_MainTexture': Shader3D.PERIOD_MATERIAL,
|
||
'u_MainColor': Shader3D.PERIOD_MATERIAL,
|
||
'u_CurTime': Shader3D.PERIOD_SPRITE,
|
||
'u_LifeTime': Shader3D.PERIOD_SPRITE,
|
||
'u_WidthCurve': Shader3D.PERIOD_SPRITE,
|
||
'u_WidthCurveKeyLength': Shader3D.PERIOD_SPRITE,
|
||
'u_GradientColorkey': Shader3D.PERIOD_SPRITE,
|
||
'u_GradientAlphakey': Shader3D.PERIOD_SPRITE
|
||
};
|
||
stateMap = {
|
||
's_Cull': Shader3D.RENDER_STATE_CULL,
|
||
's_Blend': Shader3D.RENDER_STATE_BLEND,
|
||
's_BlendSrc': Shader3D.RENDER_STATE_BLEND_SRC,
|
||
's_BlendDst': Shader3D.RENDER_STATE_BLEND_DST,
|
||
's_DepthTest': Shader3D.RENDER_STATE_DEPTH_TEST,
|
||
's_DepthWrite': Shader3D.RENDER_STATE_DEPTH_WRITE
|
||
};
|
||
shader = Shader3D.add("Trail");
|
||
subShader = new SubShader(attributeMap, uniformMap);
|
||
shader.addSubShader(subShader);
|
||
subShader.addShaderPass(TrailVS, TrailPS, stateMap);
|
||
attributeMap = {
|
||
'a_Position': VertexMesh.MESH_POSITION0,
|
||
'a_Normal': VertexMesh.MESH_NORMAL0,
|
||
'a_Tangent0': VertexMesh.MESH_TANGENT0
|
||
};
|
||
uniformMap = {
|
||
'u_MvpMatrix': Shader3D.PERIOD_SPRITE,
|
||
'u_WorldMat': Shader3D.PERIOD_SPRITE,
|
||
'u_CameraPos': Shader3D.PERIOD_CAMERA,
|
||
'u_Time': Shader3D.PERIOD_SCENE,
|
||
'u_MainTexture': Shader3D.PERIOD_MATERIAL,
|
||
'u_NormalTexture': Shader3D.PERIOD_MATERIAL,
|
||
'u_HorizonColor': Shader3D.PERIOD_MATERIAL,
|
||
'u_WaveScale': Shader3D.PERIOD_MATERIAL,
|
||
'u_WaveSpeed': Shader3D.PERIOD_MATERIAL
|
||
};
|
||
shader = Shader3D.add("WaterPrimary");
|
||
subShader = new SubShader(attributeMap, uniformMap);
|
||
shader.addSubShader(subShader);
|
||
subShader.addShaderPass(WaterPrimaryVS, WaterPrimaryPS);
|
||
attributeMap = {
|
||
'a_PositionTexcoord': VertexMesh.MESH_POSITION0
|
||
};
|
||
uniformMap = {
|
||
'u_MainTex': Shader3D.PERIOD_MATERIAL,
|
||
'u_OffsetScale': Shader3D.PERIOD_MATERIAL
|
||
};
|
||
shader = Shader3D.add("BlitScreen");
|
||
subShader = new SubShader(attributeMap, uniformMap);
|
||
shader.addSubShader(subShader);
|
||
var shaderPass = subShader.addShaderPass(BlitScreenVS, BlitScreenPS);
|
||
var renderState = shaderPass.renderState;
|
||
renderState.depthTest = RenderState.DEPTHTEST_ALWAYS;
|
||
renderState.depthWrite = false;
|
||
renderState.cull = RenderState.CULL_NONE;
|
||
renderState.blend = RenderState.BLEND_DISABLE;
|
||
attributeMap = {
|
||
'a_PositionTexcoord': VertexMesh.MESH_POSITION0
|
||
};
|
||
uniformMap = {
|
||
'u_MainTex': Shader3D.PERIOD_MATERIAL,
|
||
'u_BloomTex': Shader3D.PERIOD_MATERIAL,
|
||
'u_AutoExposureTex': Shader3D.PERIOD_MATERIAL,
|
||
'u_MainTex_TexelSize': Shader3D.PERIOD_MATERIAL,
|
||
'u_SampleScale': Shader3D.PERIOD_MATERIAL,
|
||
'u_Threshold': Shader3D.PERIOD_MATERIAL,
|
||
'u_Params': Shader3D.PERIOD_MATERIAL
|
||
};
|
||
shader = Shader3D.add("PostProcessBloom");
|
||
subShader = new SubShader(attributeMap, uniformMap);
|
||
shader.addSubShader(subShader);
|
||
shaderPass = subShader.addShaderPass(BloomVS, BloomPrefilter13PS);
|
||
renderState = shaderPass.renderState;
|
||
renderState.depthTest = RenderState.DEPTHTEST_ALWAYS;
|
||
renderState.depthWrite = false;
|
||
renderState.cull = RenderState.CULL_NONE;
|
||
renderState.blend = RenderState.BLEND_DISABLE;
|
||
subShader = new SubShader(attributeMap, uniformMap);
|
||
shader.addSubShader(subShader);
|
||
shaderPass = subShader.addShaderPass(BloomVS, BloomPrefilter4PS);
|
||
renderState = shaderPass.renderState;
|
||
renderState.depthTest = RenderState.DEPTHTEST_ALWAYS;
|
||
renderState.depthWrite = false;
|
||
renderState.cull = RenderState.CULL_NONE;
|
||
renderState.blend = RenderState.BLEND_DISABLE;
|
||
subShader = new SubShader(attributeMap, uniformMap);
|
||
shader.addSubShader(subShader);
|
||
shaderPass = subShader.addShaderPass(BloomVS, BloomDownsample13PS);
|
||
renderState = shaderPass.renderState;
|
||
renderState.depthTest = RenderState.DEPTHTEST_ALWAYS;
|
||
renderState.depthWrite = false;
|
||
renderState.cull = RenderState.CULL_NONE;
|
||
renderState.blend = RenderState.BLEND_DISABLE;
|
||
subShader = new SubShader(attributeMap, uniformMap);
|
||
shader.addSubShader(subShader);
|
||
shaderPass = subShader.addShaderPass(BloomVS, BloomDownsample4PS);
|
||
renderState = shaderPass.renderState;
|
||
renderState.depthTest = RenderState.DEPTHTEST_ALWAYS;
|
||
renderState.depthWrite = false;
|
||
renderState.cull = RenderState.CULL_NONE;
|
||
renderState.blend = RenderState.BLEND_DISABLE;
|
||
subShader = new SubShader(attributeMap, uniformMap);
|
||
shader.addSubShader(subShader);
|
||
shaderPass = subShader.addShaderPass(BloomVS, BloomUpsampleTentPS);
|
||
renderState = shaderPass.renderState;
|
||
renderState.depthTest = RenderState.DEPTHTEST_ALWAYS;
|
||
renderState.depthWrite = false;
|
||
renderState.cull = RenderState.CULL_NONE;
|
||
renderState.blend = RenderState.BLEND_DISABLE;
|
||
subShader = new SubShader(attributeMap, uniformMap);
|
||
shader.addSubShader(subShader);
|
||
shaderPass = subShader.addShaderPass(BloomVS, BloomUpsampleBoxPS);
|
||
renderState = shaderPass.renderState;
|
||
renderState.depthTest = RenderState.DEPTHTEST_ALWAYS;
|
||
renderState.depthWrite = false;
|
||
renderState.cull = RenderState.CULL_NONE;
|
||
renderState.blend = RenderState.BLEND_DISABLE;
|
||
attributeMap = {
|
||
'a_PositionTexcoord': VertexMesh.MESH_POSITION0
|
||
};
|
||
uniformMap = {
|
||
'u_MainTex': Shader3D.PERIOD_MATERIAL,
|
||
'u_BloomTex': Shader3D.PERIOD_MATERIAL,
|
||
'u_AutoExposureTex': Shader3D.PERIOD_MATERIAL,
|
||
'u_Bloom_DirtTileOffset': Shader3D.PERIOD_MATERIAL,
|
||
'u_Bloom_DirtTex': Shader3D.PERIOD_MATERIAL,
|
||
'u_BloomTex_TexelSize': Shader3D.PERIOD_MATERIAL,
|
||
'u_Bloom_Settings': Shader3D.PERIOD_MATERIAL,
|
||
'u_Bloom_Color': Shader3D.PERIOD_MATERIAL
|
||
};
|
||
shader = Shader3D.add("PostProcessComposite");
|
||
subShader = new SubShader(attributeMap, uniformMap);
|
||
shader.addSubShader(subShader);
|
||
shaderPass = subShader.addShaderPass(CompositeVS, CompositePS);
|
||
renderState = shaderPass.renderState;
|
||
renderState.depthTest = RenderState.DEPTHTEST_ALWAYS;
|
||
renderState.depthWrite = false;
|
||
renderState.cull = RenderState.CULL_NONE;
|
||
renderState.blend = RenderState.BLEND_DISABLE;
|
||
}
|
||
}
|
||
|
||
class DirectionLight extends LightSprite {
|
||
constructor() {
|
||
super();
|
||
this._direction = new Vector3();
|
||
this._shadowCascadesMode = exports.ShadowCascadesMode.NoCascades;
|
||
this._shadowTwoCascadeSplits = 1.0 / 3.0;
|
||
this._shadowFourCascadeSplits = new Vector3(1.0 / 15, 3.0 / 15.0, 7.0 / 15.0);
|
||
this._lightType = exports.LightType.Directional;
|
||
}
|
||
get shadowCascadesMode() {
|
||
return this._shadowCascadesMode;
|
||
}
|
||
set shadowCascadesMode(value) {
|
||
this._shadowCascadesMode = value;
|
||
}
|
||
get shadowTwoCascadeSplits() {
|
||
return this._shadowTwoCascadeSplits;
|
||
}
|
||
set shadowTwoCascadeSplits(value) {
|
||
this._shadowTwoCascadeSplits = value;
|
||
}
|
||
get shadowFourCascadeSplits() {
|
||
return this._shadowFourCascadeSplits;
|
||
}
|
||
set shadowFourCascadeSplits(value) {
|
||
if (value.x > value.y || value.y > value.z || value.z > 1.0)
|
||
throw "DiretionLight:Invalid value.";
|
||
value.cloneTo(this._shadowFourCascadeSplits);
|
||
}
|
||
_addToLightQueue() {
|
||
this._scene._directionLights.add(this);
|
||
}
|
||
_removeFromLightQueue() {
|
||
this._scene._directionLights.remove(this);
|
||
}
|
||
_create() {
|
||
return new DirectionLight();
|
||
}
|
||
}
|
||
|
||
class PointLight extends LightSprite {
|
||
constructor() {
|
||
super();
|
||
this._range = 6.0;
|
||
this._lightType = exports.LightType.Point;
|
||
}
|
||
get range() {
|
||
return this._range;
|
||
}
|
||
set range(value) {
|
||
this._range = value;
|
||
}
|
||
_addToLightQueue() {
|
||
this._scene._pointLights.add(this);
|
||
}
|
||
_removeFromLightQueue() {
|
||
this._scene._pointLights.remove(this);
|
||
}
|
||
_parse(data, spriteMap) {
|
||
super._parse(data, spriteMap);
|
||
this.range = data.range;
|
||
}
|
||
_cloneTo(destObject, rootSprite, dstSprite) {
|
||
super._cloneTo(destObject, rootSprite, dstSprite);
|
||
var pointlight = destObject;
|
||
pointlight.range = this.range;
|
||
pointlight._lightType = exports.LightType.Point;
|
||
}
|
||
_create() {
|
||
return new PointLight();
|
||
}
|
||
}
|
||
|
||
class SpotLight extends LightSprite {
|
||
constructor() {
|
||
super();
|
||
this._spotAngle = 30.0;
|
||
this._range = 10.0;
|
||
this._direction = new Vector3();
|
||
this._lightType = exports.LightType.Spot;
|
||
}
|
||
get spotAngle() {
|
||
return this._spotAngle;
|
||
}
|
||
set spotAngle(value) {
|
||
this._spotAngle = Math.max(Math.min(value, 179), 0);
|
||
}
|
||
get range() {
|
||
return this._range;
|
||
}
|
||
set range(value) {
|
||
this._range = value;
|
||
}
|
||
_addToLightQueue() {
|
||
this._scene._spotLights.add(this);
|
||
}
|
||
_removeFromLightQueue() {
|
||
this._scene._spotLights.remove(this);
|
||
}
|
||
_parse(data, spriteMap) {
|
||
super._parse(data, spriteMap);
|
||
this.range = data.range;
|
||
this.spotAngle = data.spotAngle;
|
||
}
|
||
_cloneTo(destObject, rootSprite, dstSprite) {
|
||
super._cloneTo(destObject, rootSprite, dstSprite);
|
||
var spotLight = destObject;
|
||
spotLight.range = this.range;
|
||
spotLight.spotAngle = this.spotAngle;
|
||
}
|
||
_create() {
|
||
return new SpotLight();
|
||
}
|
||
}
|
||
|
||
class SimpleSkinnedMeshRenderer extends SkinnedMeshRenderer {
|
||
constructor(owner) {
|
||
super(owner);
|
||
this._simpleAnimatorParams = new Vector4();
|
||
this._simpleAnimatorOffset = new Vector2();
|
||
this._shaderValues.addDefine(SkinnedMeshSprite3DShaderDeclaration.SHADERDEFINE_SIMPLEBONE);
|
||
this._shaderValues.addDefine(SkinnedMeshSprite3DShaderDeclaration.SHADERDEFINE_BONE);
|
||
}
|
||
get simpleAnimatorTexture() {
|
||
return this._simpleAnimatorTexture;
|
||
}
|
||
set simpleAnimatorTexture(value) {
|
||
this._simpleAnimatorTexture = value;
|
||
this._simpleAnimatorTextureSize = value.width;
|
||
this._shaderValues.setTexture(SimpleSkinnedMeshRenderer.SIMPLE_SIMPLEANIMATORTEXTURE, value);
|
||
value._addReference();
|
||
this._shaderValues.setNumber(SimpleSkinnedMeshRenderer.SIMPLE_SIMPLEANIMATORTEXTURESIZE, this._simpleAnimatorTextureSize);
|
||
}
|
||
get simpleAnimatorOffset() {
|
||
return this._simpleAnimatorOffset;
|
||
}
|
||
set simpleAnimatorOffset(value) {
|
||
value.cloneTo(this._simpleAnimatorOffset);
|
||
}
|
||
_computeAnimatorParamsData() {
|
||
if (this._cacheMesh) {
|
||
this._simpleAnimatorParams.x = this._simpleAnimatorOffset.x;
|
||
this._simpleAnimatorParams.y = Math.round(this._simpleAnimatorOffset.y) * this._bonesNums * 4;
|
||
}
|
||
}
|
||
_createRenderElement() {
|
||
return new SubMeshRenderElement();
|
||
}
|
||
_setCacheAnimator(animator) {
|
||
this._cacheAnimator = animator;
|
||
this._shaderValues.addDefine(SkinnedMeshSprite3DShaderDeclaration.SHADERDEFINE_SIMPLEBONE);
|
||
}
|
||
_onMeshChange(value) {
|
||
super._onMeshChange(value);
|
||
this._cacheMesh = value;
|
||
}
|
||
_renderUpdate(context, transform) {
|
||
var element = context.renderElement;
|
||
switch (element.renderType) {
|
||
case RenderElement.RENDERTYPE_NORMAL:
|
||
if (this._cacheAnimator) {
|
||
var worldMat = this._cacheAnimator.owner.transform.worldMatrix;
|
||
this._shaderValues.setMatrix4x4(Sprite3D.WORLDMATRIX, worldMat);
|
||
}
|
||
else {
|
||
this._shaderValues.setMatrix4x4(Sprite3D.WORLDMATRIX, transform.worldMatrix);
|
||
}
|
||
this._computeAnimatorParamsData();
|
||
this._shaderValues.setVector(SimpleSkinnedMeshRenderer.SIMPLE_SIMPLEANIMATORPARAMS, this._simpleAnimatorParams);
|
||
break;
|
||
case RenderElement.RENDERTYPE_INSTANCEBATCH:
|
||
var worldMatrixData = SubMeshInstanceBatch.instance.instanceWorldMatrixData;
|
||
var insBatches = element.instanceBatchElementList;
|
||
var elements = insBatches.elements;
|
||
var count = insBatches.length;
|
||
if (this._cacheAnimator) {
|
||
for (var i = 0; i < count; i++) {
|
||
var mat = (elements[i].render)._cacheAnimator.owner._transform.worldMatrix;
|
||
worldMatrixData.set(mat.elements, i * 16);
|
||
}
|
||
}
|
||
else {
|
||
for (var i = 0; i < count; i++)
|
||
worldMatrixData.set(elements[i]._transform.worldMatrix.elements, i * 16);
|
||
}
|
||
var worldBuffer = SubMeshInstanceBatch.instance.instanceWorldMatrixBuffer;
|
||
worldBuffer.orphanStorage();
|
||
worldBuffer.setData(worldMatrixData.buffer, 0, 0, count * 16 * 4);
|
||
this._shaderValues.addDefine(MeshSprite3DShaderDeclaration.SHADERDEFINE_GPU_INSTANCE);
|
||
var simpleAnimatorData = SubMeshInstanceBatch.instance.instanceSimpleAnimatorData;
|
||
if (this._cacheAnimator) {
|
||
for (var i = 0; i < count; i++) {
|
||
var render = (elements[i].render);
|
||
render._computeAnimatorParamsData();
|
||
var simpleAnimatorParams = render._simpleAnimatorParams;
|
||
var offset = i * 4;
|
||
simpleAnimatorData[offset] = simpleAnimatorParams.x;
|
||
simpleAnimatorData[offset + 1] = simpleAnimatorParams.y;
|
||
}
|
||
}
|
||
else {
|
||
for (var i = 0; i < count; i++) {
|
||
simpleAnimatorData[offset] = 0;
|
||
simpleAnimatorData[offset + 1] = 0;
|
||
}
|
||
}
|
||
var simpleAnimatorBuffer = SubMeshInstanceBatch.instance.instanceSimpleAnimatorBuffer;
|
||
simpleAnimatorBuffer.orphanStorage();
|
||
simpleAnimatorBuffer.setData(simpleAnimatorData.buffer, 0, 0, count * 4 * 4);
|
||
break;
|
||
}
|
||
}
|
||
_renderUpdateWithCamera(context, transform) {
|
||
var projectionView = context.projectionViewMatrix;
|
||
if (projectionView) {
|
||
var element = context.renderElement;
|
||
switch (element.renderType) {
|
||
case RenderElement.RENDERTYPE_NORMAL:
|
||
if (this._cacheAnimator) {
|
||
var mat = this._cacheAnimator.owner._transform.worldMatrix;
|
||
Matrix4x4.multiply(projectionView, mat, this._projectionViewWorldMatrix);
|
||
this._shaderValues.setMatrix4x4(Sprite3D.MVPMATRIX, this._projectionViewWorldMatrix);
|
||
}
|
||
else {
|
||
Matrix4x4.multiply(projectionView, transform.worldMatrix, this._projectionViewWorldMatrix);
|
||
this._shaderValues.setMatrix4x4(Sprite3D.MVPMATRIX, this._projectionViewWorldMatrix);
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
_destroy() {
|
||
if (this._cacheRootBone)
|
||
(!this._cacheRootBone.destroyed) && (this._cacheRootBone.transform.off(Laya.Event.TRANSFORM_CHANGED, this, this._onWorldMatNeedChange));
|
||
(this._simpleAnimatorTexture) && this._simpleAnimatorTexture._removeReference();
|
||
this._simpleAnimatorTexture = null;
|
||
}
|
||
}
|
||
|
||
class SimpleSkinnedMeshSprite3D extends RenderableSprite3D {
|
||
constructor(mesh = null, name = null) {
|
||
super(name);
|
||
this._meshFilter = new MeshFilter(this);
|
||
this._render = new SimpleSkinnedMeshRenderer(this);
|
||
(mesh) && (this._meshFilter.sharedMesh = mesh);
|
||
}
|
||
static __init__() {
|
||
SimpleSkinnedMeshRenderer.SIMPLE_SIMPLEANIMATORPARAMS = SimpleSkinnedMeshSprite3D.SIMPLE_SIMPLEANIMATORPARAMS;
|
||
SimpleSkinnedMeshRenderer.SIMPLE_SIMPLEANIMATORTEXTURE = SimpleSkinnedMeshSprite3D.SIMPLE_SIMPLEANIMATORTEXTURE;
|
||
SimpleSkinnedMeshRenderer.SIMPLE_SIMPLEANIMATORTEXTURESIZE = SimpleSkinnedMeshSprite3D.SIMPLE_SIMPLEANIMATORTEXTURESIZE;
|
||
}
|
||
get meshFilter() {
|
||
return this._meshFilter;
|
||
}
|
||
get simpleSkinnedMeshRenderer() {
|
||
return this._render;
|
||
}
|
||
_parse(data, spriteMap) {
|
||
super._parse(data, spriteMap);
|
||
var render = this.simpleSkinnedMeshRenderer;
|
||
var lightmapIndex = data.lightmapIndex;
|
||
(lightmapIndex != null) && (render.lightmapIndex = lightmapIndex);
|
||
var lightmapScaleOffsetArray = data.lightmapScaleOffset;
|
||
(lightmapScaleOffsetArray) && (render.lightmapScaleOffset = new Vector4(lightmapScaleOffsetArray[0], lightmapScaleOffsetArray[1], lightmapScaleOffsetArray[2], lightmapScaleOffsetArray[3]));
|
||
(data.enableRender != undefined) && (render.enable = data.enableRender);
|
||
(data.receiveShadows != undefined) && (render.receiveShadow = data.receiveShadows);
|
||
(data.castShadow != undefined) && (render.castShadow = data.castShadow);
|
||
var meshPath;
|
||
meshPath = data.meshPath;
|
||
if (meshPath) {
|
||
var mesh = Laya.Loader.getRes(meshPath);
|
||
(mesh) && (this.meshFilter.sharedMesh = mesh);
|
||
}
|
||
var materials = data.materials;
|
||
if (materials) {
|
||
var sharedMaterials = render.sharedMaterials;
|
||
var materialCount = materials.length;
|
||
sharedMaterials.length = materialCount;
|
||
for (var i = 0; i < materialCount; i++) {
|
||
sharedMaterials[i] = Laya.Loader.getRes(materials[i].path);
|
||
}
|
||
render.sharedMaterials = sharedMaterials;
|
||
}
|
||
var boundBox = data.boundBox;
|
||
var min = boundBox.min;
|
||
var max = boundBox.max;
|
||
render.localBounds.setMin(new Vector3(min[0], min[1], min[2]));
|
||
render.localBounds.setMax(new Vector3(max[0], max[1], max[2]));
|
||
if (spriteMap) {
|
||
var rootBoneData = data.rootBone;
|
||
render.rootBone = spriteMap[rootBoneData];
|
||
var bonesData = data.bones;
|
||
var n;
|
||
for (i = 0, n = bonesData.length; i < n; i++)
|
||
render.bones.push(spriteMap[bonesData[i]]);
|
||
render._bonesNums = data.bonesNums ? data.bonesNums : render.bones.length;
|
||
}
|
||
else {
|
||
(data.rootBone) && (render._setRootBone(data.rootBone));
|
||
}
|
||
var animatorTexture = data.animatorTexture;
|
||
if (animatorTexture) {
|
||
var animatortexture = Laya.Loader.getRes(animatorTexture);
|
||
render.simpleAnimatorTexture = animatortexture;
|
||
}
|
||
}
|
||
_changeHierarchyAnimator(animator) {
|
||
super._changeHierarchyAnimator(animator);
|
||
this.simpleSkinnedMeshRenderer._setCacheAnimator(animator);
|
||
}
|
||
_cloneTo(destObject, srcRoot, dstRoot) {
|
||
var meshSprite3D = destObject;
|
||
meshSprite3D.meshFilter.sharedMesh = this.meshFilter.sharedMesh;
|
||
var meshRender = this._render;
|
||
var destMeshRender = meshSprite3D._render;
|
||
destMeshRender.enable = meshRender.enable;
|
||
destMeshRender.sharedMaterials = meshRender.sharedMaterials;
|
||
destMeshRender.castShadow = meshRender.castShadow;
|
||
var lightmapScaleOffset = meshRender.lightmapScaleOffset;
|
||
lightmapScaleOffset && (destMeshRender.lightmapScaleOffset = lightmapScaleOffset.clone());
|
||
destMeshRender.receiveShadow = meshRender.receiveShadow;
|
||
destMeshRender.sortingFudge = meshRender.sortingFudge;
|
||
destMeshRender._rootBone = meshRender._rootBone;
|
||
var bones = meshRender.bones;
|
||
var destBones = destMeshRender.bones;
|
||
var bonesCount = bones.length;
|
||
destBones.length = bonesCount;
|
||
var rootBone = meshRender.rootBone;
|
||
if (rootBone) {
|
||
var pathes = Utils3D._getHierarchyPath(srcRoot, rootBone, SimpleSkinnedMeshSprite3D._tempArray0);
|
||
if (pathes)
|
||
destMeshRender.rootBone = Utils3D._getNodeByHierarchyPath(dstRoot, pathes);
|
||
else
|
||
destMeshRender.rootBone = rootBone;
|
||
}
|
||
for (var i = 0; i < bones.length; i++) {
|
||
pathes = Utils3D._getHierarchyPath(srcRoot, bones[i], SimpleSkinnedMeshSprite3D._tempArray0);
|
||
if (pathes)
|
||
destBones[i] = Utils3D._getNodeByHierarchyPath(dstRoot, pathes);
|
||
else
|
||
destBones[i] = bones[i];
|
||
}
|
||
var lbb = meshRender.localBounds;
|
||
(lbb) && (lbb.cloneTo(destMeshRender.localBounds));
|
||
destMeshRender.simpleAnimatorOffset = meshRender.simpleAnimatorOffset;
|
||
destMeshRender.simpleAnimatorTexture = meshRender.simpleAnimatorTexture;
|
||
destMeshRender._bonesNums = meshRender._bonesNums;
|
||
super._cloneTo(destObject, srcRoot, dstRoot);
|
||
}
|
||
destroy(destroyChild = true) {
|
||
if (this.destroyed)
|
||
return;
|
||
super.destroy(destroyChild);
|
||
this._meshFilter.destroy();
|
||
}
|
||
_create() {
|
||
return new SimpleSkinnedMeshSprite3D();
|
||
}
|
||
}
|
||
SimpleSkinnedMeshSprite3D._tempArray0 = [];
|
||
SimpleSkinnedMeshSprite3D.SIMPLE_SIMPLEANIMATORTEXTURE = Shader3D.propertyNameToID("u_SimpleAnimatorTexture");
|
||
SimpleSkinnedMeshSprite3D.SIMPLE_SIMPLEANIMATORPARAMS = Shader3D.propertyNameToID("u_SimpleAnimatorParams");
|
||
SimpleSkinnedMeshSprite3D.SIMPLE_SIMPLEANIMATORTEXTURESIZE = Shader3D.propertyNameToID("u_SimpleAnimatorTextureSize");
|
||
|
||
class Scene3DUtils {
|
||
static _createSprite3DInstance(nodeData, spriteMap, outBatchSprites) {
|
||
var node;
|
||
switch (nodeData.type) {
|
||
case "Scene3D":
|
||
node = new Scene3D();
|
||
break;
|
||
case "Sprite3D":
|
||
node = new Sprite3D();
|
||
break;
|
||
case "MeshSprite3D":
|
||
node = new MeshSprite3D();
|
||
(outBatchSprites && nodeData.props.isStatic) && (outBatchSprites.push(node));
|
||
break;
|
||
case "SkinnedMeshSprite3D":
|
||
node = new SkinnedMeshSprite3D();
|
||
break;
|
||
case "SimpleSkinnedMeshSprite3D":
|
||
node = new SimpleSkinnedMeshSprite3D();
|
||
break;
|
||
case "ShuriKenParticle3D":
|
||
node = new ShuriKenParticle3D();
|
||
break;
|
||
case "Camera":
|
||
node = new Camera();
|
||
break;
|
||
case "DirectionLight":
|
||
node = new DirectionLight();
|
||
break;
|
||
case "PointLight":
|
||
node = new PointLight();
|
||
break;
|
||
case "SpotLight":
|
||
node = new SpotLight();
|
||
break;
|
||
case "TrailSprite3D":
|
||
node = new TrailSprite3D();
|
||
break;
|
||
case "ReflectionProbe":
|
||
node = new ReflectionProbe();
|
||
break;
|
||
default:
|
||
throw new Error("Utils3D:unidentified class type in (.lh) file.");
|
||
}
|
||
var childData = nodeData.child;
|
||
if (childData) {
|
||
for (var i = 0, n = childData.length; i < n; i++) {
|
||
var child = Scene3DUtils._createSprite3DInstance(childData[i], spriteMap, outBatchSprites);
|
||
node.addChild(child);
|
||
}
|
||
}
|
||
spriteMap[nodeData.instanceID] = node;
|
||
return node;
|
||
}
|
||
static _createComponentInstance(nodeData, spriteMap, interactMap) {
|
||
var node = spriteMap[nodeData.instanceID];
|
||
node._parse(nodeData.props, spriteMap);
|
||
var childData = nodeData.child;
|
||
if (childData) {
|
||
for (var i = 0, n = childData.length; i < n; i++)
|
||
Scene3DUtils._createComponentInstance(childData[i], spriteMap, interactMap);
|
||
}
|
||
var componentsData = nodeData.components;
|
||
if (componentsData) {
|
||
for (var j = 0, m = componentsData.length; j < m; j++) {
|
||
var data = componentsData[j];
|
||
var clas = Laya.ClassUtils.getRegClass(data.type);
|
||
if (clas) {
|
||
var component = node.addComponent(clas);
|
||
component._parse(data, interactMap);
|
||
}
|
||
else {
|
||
console.warn("Unkown component type.");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
static _createNodeByJson02(nodeData, outBatchSprites) {
|
||
var spriteMap = {};
|
||
var interactMap = { component: [], data: [] };
|
||
var node = Scene3DUtils._createSprite3DInstance(nodeData, spriteMap, outBatchSprites);
|
||
Scene3DUtils._createComponentInstance(nodeData, spriteMap, interactMap);
|
||
Scene3DUtils._createInteractInstance(interactMap, spriteMap);
|
||
return node;
|
||
}
|
||
static _createInteractInstance(interatMap, spriteMap) {
|
||
var components = interatMap.component;
|
||
var data = interatMap.data;
|
||
for (var i = 0, n = components.length; i < n; i++) {
|
||
components[i]._parseInteractive(data[i], spriteMap);
|
||
}
|
||
}
|
||
static _parse(data, propertyParams = null, constructParams = null) {
|
||
var json = data.data;
|
||
var outBatchSprits = [];
|
||
var sprite;
|
||
switch (data.version) {
|
||
case "LAYAHIERARCHY:02":
|
||
sprite = Scene3DUtils._createNodeByJson02(json, outBatchSprits);
|
||
break;
|
||
default:
|
||
sprite = Scene3DUtils._createNodeByJson(json, outBatchSprits);
|
||
}
|
||
StaticBatchManager.combine(sprite, outBatchSprits);
|
||
return sprite;
|
||
}
|
||
static _parseScene(data, propertyParams = null, constructParams = null) {
|
||
var json = data.data;
|
||
var outBatchSprits = [];
|
||
var scene;
|
||
switch (data.version) {
|
||
case "LAYASCENE3D:02":
|
||
scene = Scene3DUtils._createNodeByJson02(json, outBatchSprits);
|
||
break;
|
||
default:
|
||
scene = Scene3DUtils._createNodeByJson(json, outBatchSprits);
|
||
}
|
||
StaticBatchManager.combine(null, outBatchSprits);
|
||
return scene;
|
||
}
|
||
static _createNodeByJson(nodeData, outBatchSprites) {
|
||
var node;
|
||
switch (nodeData.type) {
|
||
case "Scene3D":
|
||
node = new Scene3D();
|
||
break;
|
||
case "Sprite3D":
|
||
node = new Sprite3D();
|
||
break;
|
||
case "MeshSprite3D":
|
||
node = new MeshSprite3D();
|
||
(outBatchSprites && nodeData.props.isStatic) && (outBatchSprites.push(node));
|
||
break;
|
||
case "SkinnedMeshSprite3D":
|
||
node = new SkinnedMeshSprite3D();
|
||
break;
|
||
case "ShuriKenParticle3D":
|
||
node = new ShuriKenParticle3D();
|
||
break;
|
||
case "Camera":
|
||
node = new Camera();
|
||
break;
|
||
case "DirectionLight":
|
||
node = new DirectionLight();
|
||
break;
|
||
case "PointLight":
|
||
node = new PointLight();
|
||
break;
|
||
case "SpotLight":
|
||
node = new SpotLight();
|
||
break;
|
||
case "TrailSprite3D":
|
||
node = new TrailSprite3D();
|
||
break;
|
||
default:
|
||
throw new Error("Utils3D:unidentified class type in (.lh) file.");
|
||
}
|
||
var childData = nodeData.child;
|
||
if (childData) {
|
||
for (var i = 0, n = childData.length; i < n; i++) {
|
||
var child = Scene3DUtils._createNodeByJson(childData[i], outBatchSprites);
|
||
node.addChild(child);
|
||
}
|
||
}
|
||
var componentsData = nodeData.components;
|
||
if (componentsData) {
|
||
for (var j = 0, m = componentsData.length; j < m; j++) {
|
||
var data = componentsData[j];
|
||
var clas = Laya.ClassUtils.getRegClass(data.type);
|
||
if (clas) {
|
||
var component = node.addComponent(clas);
|
||
component._parse(data);
|
||
}
|
||
else {
|
||
console.warn("Unkown component type.");
|
||
}
|
||
}
|
||
}
|
||
node._parse(nodeData.props, null);
|
||
return node;
|
||
}
|
||
}
|
||
|
||
class LoadModelV04 {
|
||
static parse(readData, version, mesh, subMeshes) {
|
||
LoadModelV04._mesh = mesh;
|
||
LoadModelV04._subMeshes = subMeshes;
|
||
LoadModelV04._version = version;
|
||
LoadModelV04._readData = readData;
|
||
LoadModelV04.READ_DATA();
|
||
LoadModelV04.READ_BLOCK();
|
||
LoadModelV04.READ_STRINGS();
|
||
for (var i = 0, n = LoadModelV04._BLOCK.count; i < n; i++) {
|
||
LoadModelV04._readData.pos = LoadModelV04._BLOCK.blockStarts[i];
|
||
var index = LoadModelV04._readData.getUint16();
|
||
var blockName = LoadModelV04._strings[index];
|
||
var fn = LoadModelV04["READ_" + blockName];
|
||
if (fn == null)
|
||
throw new Error("model file err,no this function:" + index + " " + blockName);
|
||
else
|
||
fn.call(null);
|
||
}
|
||
LoadModelV04._strings.length = 0;
|
||
LoadModelV04._readData = null;
|
||
LoadModelV04._version = null;
|
||
LoadModelV04._mesh = null;
|
||
LoadModelV04._subMeshes = null;
|
||
}
|
||
static _readString() {
|
||
return LoadModelV04._strings[LoadModelV04._readData.getUint16()];
|
||
}
|
||
static READ_DATA() {
|
||
LoadModelV04._DATA.offset = LoadModelV04._readData.getUint32();
|
||
LoadModelV04._DATA.size = LoadModelV04._readData.getUint32();
|
||
}
|
||
static READ_BLOCK() {
|
||
var count = LoadModelV04._BLOCK.count = LoadModelV04._readData.getUint16();
|
||
var blockStarts = LoadModelV04._BLOCK.blockStarts = [];
|
||
var blockLengths = LoadModelV04._BLOCK.blockLengths = [];
|
||
for (var i = 0; i < count; i++) {
|
||
blockStarts.push(LoadModelV04._readData.getUint32());
|
||
blockLengths.push(LoadModelV04._readData.getUint32());
|
||
}
|
||
}
|
||
static READ_STRINGS() {
|
||
var offset = LoadModelV04._readData.getUint32();
|
||
var count = LoadModelV04._readData.getUint16();
|
||
var prePos = LoadModelV04._readData.pos;
|
||
LoadModelV04._readData.pos = offset + LoadModelV04._DATA.offset;
|
||
for (var i = 0; i < count; i++)
|
||
LoadModelV04._strings[i] = LoadModelV04._readData.readUTFString();
|
||
LoadModelV04._readData.pos = prePos;
|
||
}
|
||
static READ_MESH() {
|
||
var gl = Laya.LayaGL.instance;
|
||
var name = LoadModelV04._readString();
|
||
var arrayBuffer = LoadModelV04._readData.__getBuffer();
|
||
var i;
|
||
var memorySize = 0;
|
||
var vertexBufferCount = LoadModelV04._readData.getInt16();
|
||
var offset = LoadModelV04._DATA.offset;
|
||
for (i = 0; i < vertexBufferCount; i++) {
|
||
var vbStart = offset + LoadModelV04._readData.getUint32();
|
||
var vbLength = LoadModelV04._readData.getUint32();
|
||
var vbArrayBuffer = arrayBuffer.slice(vbStart, vbStart + vbLength);
|
||
var vbDatas = new Float32Array(vbArrayBuffer);
|
||
var bufferAttribute = LoadModelV04._readString();
|
||
var vertexDeclaration;
|
||
switch (LoadModelV04._version) {
|
||
case "LAYAMODEL:0301":
|
||
case "LAYAMODEL:0400":
|
||
vertexDeclaration = VertexMesh.getVertexDeclaration(bufferAttribute);
|
||
break;
|
||
case "LAYAMODEL:0401":
|
||
vertexDeclaration = VertexMesh.getVertexDeclaration(bufferAttribute, false);
|
||
break;
|
||
default:
|
||
throw new Error("LoadModelV03: unknown version.");
|
||
}
|
||
if (!vertexDeclaration)
|
||
throw new Error("LoadModelV03: unknown vertexDeclaration.");
|
||
var vertexBuffer = new VertexBuffer3D(vbDatas.length * 4, gl.STATIC_DRAW, true);
|
||
vertexBuffer.vertexDeclaration = vertexDeclaration;
|
||
vertexBuffer.setData(vbDatas.buffer);
|
||
LoadModelV04._mesh._vertexBuffer = vertexBuffer;
|
||
LoadModelV04._mesh._vertexCount += vertexBuffer._byteLength / vertexDeclaration.vertexStride;
|
||
memorySize += vbDatas.length * 4;
|
||
}
|
||
var ibStart = offset + LoadModelV04._readData.getUint32();
|
||
var ibLength = LoadModelV04._readData.getUint32();
|
||
var ibDatas = new Uint16Array(arrayBuffer.slice(ibStart, ibStart + ibLength));
|
||
var indexBuffer = new IndexBuffer3D(exports.IndexFormat.UInt16, ibLength / 2, gl.STATIC_DRAW, true);
|
||
indexBuffer.setData(ibDatas);
|
||
LoadModelV04._mesh._indexBuffer = indexBuffer;
|
||
memorySize += indexBuffer.indexCount * 2;
|
||
LoadModelV04._mesh._setBuffer(LoadModelV04._mesh._vertexBuffer, indexBuffer);
|
||
LoadModelV04._mesh._setCPUMemory(memorySize);
|
||
LoadModelV04._mesh._setGPUMemory(memorySize);
|
||
var boneNames = LoadModelV04._mesh._boneNames = [];
|
||
var boneCount = LoadModelV04._readData.getUint16();
|
||
boneNames.length = boneCount;
|
||
for (i = 0; i < boneCount; i++)
|
||
boneNames[i] = LoadModelV04._strings[LoadModelV04._readData.getUint16()];
|
||
LoadModelV04._readData.pos += 8;
|
||
var bindPoseDataStart = LoadModelV04._readData.getUint32();
|
||
var bindPoseDataLength = LoadModelV04._readData.getUint32();
|
||
var bindPoseDatas = new Float32Array(arrayBuffer.slice(offset + bindPoseDataStart, offset + bindPoseDataStart + bindPoseDataLength));
|
||
var bindPoseFloatCount = bindPoseDatas.length;
|
||
var bindPoseBuffer = LoadModelV04._mesh._inverseBindPosesBuffer = new ArrayBuffer(bindPoseFloatCount * 4);
|
||
LoadModelV04._mesh._inverseBindPoses = [];
|
||
if (bindPoseFloatCount != 0)
|
||
LoadModelV04._mesh._instanceBufferStateType = Mesh.MESH_INSTANCEBUFFER_TYPE_SIMPLEANIMATOR;
|
||
else
|
||
LoadModelV04._mesh._instanceBufferStateType = Mesh.MESH_INSTANCEBUFFER_TYPE_NORMAL;
|
||
LoadModelV04._mesh._setInstanceBuffer(LoadModelV04._mesh._instanceBufferStateType);
|
||
for (i = 0; i < bindPoseFloatCount; i += 16) {
|
||
var inverseGlobalBindPose = new Matrix4x4(bindPoseDatas[i + 0], bindPoseDatas[i + 1], bindPoseDatas[i + 2], bindPoseDatas[i + 3], bindPoseDatas[i + 4], bindPoseDatas[i + 5], bindPoseDatas[i + 6], bindPoseDatas[i + 7], bindPoseDatas[i + 8], bindPoseDatas[i + 9], bindPoseDatas[i + 10], bindPoseDatas[i + 11], bindPoseDatas[i + 12], bindPoseDatas[i + 13], bindPoseDatas[i + 14], bindPoseDatas[i + 15], new Float32Array(bindPoseBuffer, i * 4, 16));
|
||
LoadModelV04._mesh._inverseBindPoses[i / 16] = inverseGlobalBindPose;
|
||
}
|
||
return true;
|
||
}
|
||
static READ_SUBMESH() {
|
||
var arrayBuffer = LoadModelV04._readData.__getBuffer();
|
||
var subMesh = new SubMesh(LoadModelV04._mesh);
|
||
LoadModelV04._readData.getInt16();
|
||
LoadModelV04._readData.getUint32();
|
||
LoadModelV04._readData.getUint32();
|
||
var ibStart = LoadModelV04._readData.getUint32();
|
||
var ibCount = LoadModelV04._readData.getUint32();
|
||
var indexBuffer = LoadModelV04._mesh._indexBuffer;
|
||
subMesh._indexBuffer = indexBuffer;
|
||
subMesh._setIndexRange(ibStart, ibCount);
|
||
var vertexBuffer = LoadModelV04._mesh._vertexBuffer;
|
||
subMesh._vertexBuffer = vertexBuffer;
|
||
var offset = LoadModelV04._DATA.offset;
|
||
var subIndexBufferStart = subMesh._subIndexBufferStart;
|
||
var subIndexBufferCount = subMesh._subIndexBufferCount;
|
||
var boneIndicesList = subMesh._boneIndicesList;
|
||
var drawCount = LoadModelV04._readData.getUint16();
|
||
subIndexBufferStart.length = drawCount;
|
||
subIndexBufferCount.length = drawCount;
|
||
boneIndicesList.length = drawCount;
|
||
var skinnedCache = LoadModelV04._mesh._skinnedMatrixCaches;
|
||
var subMeshIndex = LoadModelV04._subMeshes.length;
|
||
skinnedCache.length = LoadModelV04._mesh._inverseBindPoses.length;
|
||
for (var i = 0; i < drawCount; i++) {
|
||
subIndexBufferStart[i] = LoadModelV04._readData.getUint32();
|
||
subIndexBufferCount[i] = LoadModelV04._readData.getUint32();
|
||
var boneDicofs = LoadModelV04._readData.getUint32();
|
||
var boneDicCount = LoadModelV04._readData.getUint32();
|
||
var boneIndices = boneIndicesList[i] = new Uint16Array(arrayBuffer.slice(offset + boneDicofs, offset + boneDicofs + boneDicCount));
|
||
var boneIndexCount = boneIndices.length;
|
||
for (var j = 0; j < boneIndexCount; j++) {
|
||
var index = boneIndices[j];
|
||
skinnedCache[index] || (skinnedCache[index] = new skinnedMatrixCache(subMeshIndex, i, j));
|
||
}
|
||
}
|
||
LoadModelV04._subMeshes.push(subMesh);
|
||
return true;
|
||
}
|
||
}
|
||
LoadModelV04._BLOCK = { count: 0 };
|
||
LoadModelV04._DATA = { offset: 0, size: 0 };
|
||
LoadModelV04._strings = [];
|
||
|
||
class LoadModelV05 {
|
||
static parse(readData, version, mesh, subMeshes) {
|
||
LoadModelV05._mesh = mesh;
|
||
LoadModelV05._subMeshes = subMeshes;
|
||
LoadModelV05._version = version;
|
||
LoadModelV05._readData = readData;
|
||
LoadModelV05.READ_DATA();
|
||
LoadModelV05.READ_BLOCK();
|
||
LoadModelV05.READ_STRINGS();
|
||
for (var i = 0, n = LoadModelV05._BLOCK.count; i < n; i++) {
|
||
LoadModelV05._readData.pos = LoadModelV05._BLOCK.blockStarts[i];
|
||
var index = LoadModelV05._readData.getUint16();
|
||
var blockName = LoadModelV05._strings[index];
|
||
var fn = LoadModelV05["READ_" + blockName];
|
||
if (fn == null)
|
||
throw new Error("model file err,no this function:" + index + " " + blockName);
|
||
else
|
||
fn.call(null);
|
||
}
|
||
LoadModelV05._strings.length = 0;
|
||
LoadModelV05._readData = null;
|
||
LoadModelV05._version = null;
|
||
LoadModelV05._mesh = null;
|
||
LoadModelV05._subMeshes = null;
|
||
}
|
||
static _readString() {
|
||
return LoadModelV05._strings[LoadModelV05._readData.getUint16()];
|
||
}
|
||
static READ_DATA() {
|
||
LoadModelV05._DATA.offset = LoadModelV05._readData.getUint32();
|
||
LoadModelV05._DATA.size = LoadModelV05._readData.getUint32();
|
||
}
|
||
static READ_BLOCK() {
|
||
var count = LoadModelV05._BLOCK.count = LoadModelV05._readData.getUint16();
|
||
var blockStarts = LoadModelV05._BLOCK.blockStarts = [];
|
||
var blockLengths = LoadModelV05._BLOCK.blockLengths = [];
|
||
for (var i = 0; i < count; i++) {
|
||
blockStarts.push(LoadModelV05._readData.getUint32());
|
||
blockLengths.push(LoadModelV05._readData.getUint32());
|
||
}
|
||
}
|
||
static READ_STRINGS() {
|
||
var offset = LoadModelV05._readData.getUint32();
|
||
var count = LoadModelV05._readData.getUint16();
|
||
var prePos = LoadModelV05._readData.pos;
|
||
LoadModelV05._readData.pos = offset + LoadModelV05._DATA.offset;
|
||
for (var i = 0; i < count; i++)
|
||
LoadModelV05._strings[i] = LoadModelV05._readData.readUTFString();
|
||
LoadModelV05._readData.pos = prePos;
|
||
}
|
||
static READ_MESH() {
|
||
var gl = Laya.LayaGL.instance;
|
||
var i;
|
||
var memorySize = 0;
|
||
var name = LoadModelV05._readString();
|
||
var reader = LoadModelV05._readData;
|
||
var arrayBuffer = reader.__getBuffer();
|
||
var vertexBufferCount = reader.getInt16();
|
||
var offset = LoadModelV05._DATA.offset;
|
||
for (i = 0; i < vertexBufferCount; i++) {
|
||
var vbStart = offset + reader.getUint32();
|
||
var vertexCount = reader.getUint32();
|
||
var vertexFlag = LoadModelV05._readString();
|
||
var vertexDeclaration = VertexMesh.getVertexDeclaration(vertexFlag, false);
|
||
var vertexStride = vertexDeclaration.vertexStride;
|
||
var vertexData;
|
||
var floatData;
|
||
var uint8Data;
|
||
var subVertexFlags = vertexFlag.split(",");
|
||
var subVertexCount = subVertexFlags.length;
|
||
var mesh = LoadModelV05._mesh;
|
||
switch (LoadModelV05._version) {
|
||
case "LAYAMODEL:05":
|
||
case "LAYAMODEL:0501":
|
||
vertexData = arrayBuffer.slice(vbStart, vbStart + vertexCount * vertexStride);
|
||
floatData = new Float32Array(vertexData);
|
||
uint8Data = new Uint8Array(vertexData);
|
||
break;
|
||
case "LAYAMODEL:COMPRESSION_05":
|
||
case "LAYAMODEL:COMPRESSION_0501":
|
||
vertexData = new ArrayBuffer(vertexStride * vertexCount);
|
||
floatData = new Float32Array(vertexData);
|
||
uint8Data = new Uint8Array(vertexData);
|
||
var lastPosition = reader.pos;
|
||
reader.pos = vbStart;
|
||
for (var j = 0; j < vertexCount; j++) {
|
||
var subOffset;
|
||
var verOffset = j * vertexStride;
|
||
for (var k = 0; k < subVertexCount; k++) {
|
||
switch (subVertexFlags[k]) {
|
||
case "POSITION":
|
||
subOffset = verOffset / 4;
|
||
floatData[subOffset] = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
floatData[subOffset + 1] = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
floatData[subOffset + 2] = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
verOffset += 12;
|
||
break;
|
||
case "NORMAL":
|
||
subOffset = verOffset / 4;
|
||
floatData[subOffset] = reader.getUint8() / 127.5 - 1;
|
||
floatData[subOffset + 1] = reader.getUint8() / 127.5 - 1;
|
||
floatData[subOffset + 2] = reader.getUint8() / 127.5 - 1;
|
||
verOffset += 12;
|
||
break;
|
||
case "COLOR":
|
||
subOffset = verOffset / 4;
|
||
floatData[subOffset] = reader.getUint8() / 255;
|
||
floatData[subOffset + 1] = reader.getUint8() / 255;
|
||
floatData[subOffset + 2] = reader.getUint8() / 255;
|
||
floatData[subOffset + 3] = reader.getUint8() / 255;
|
||
verOffset += 16;
|
||
break;
|
||
case "UV":
|
||
subOffset = verOffset / 4;
|
||
floatData[subOffset] = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
floatData[subOffset + 1] = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
verOffset += 8;
|
||
break;
|
||
case "UV1":
|
||
subOffset = verOffset / 4;
|
||
floatData[subOffset] = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
floatData[subOffset + 1] = Laya.HalfFloatUtils.convertToNumber(reader.getUint16());
|
||
verOffset += 8;
|
||
break;
|
||
case "BLENDWEIGHT":
|
||
subOffset = verOffset / 4;
|
||
floatData[subOffset] = reader.getUint8() / 255;
|
||
floatData[subOffset + 1] = reader.getUint8() / 255;
|
||
floatData[subOffset + 2] = reader.getUint8() / 255;
|
||
floatData[subOffset + 3] = reader.getUint8() / 255;
|
||
verOffset += 16;
|
||
break;
|
||
case "BLENDINDICES":
|
||
uint8Data[verOffset] = reader.getUint8();
|
||
uint8Data[verOffset + 1] = reader.getUint8();
|
||
uint8Data[verOffset + 2] = reader.getUint8();
|
||
uint8Data[verOffset + 3] = reader.getUint8();
|
||
verOffset += 4;
|
||
break;
|
||
case "TANGENT":
|
||
subOffset = verOffset / 4;
|
||
floatData[subOffset] = reader.getUint8() / 127.5 - 1;
|
||
floatData[subOffset + 1] = reader.getUint8() / 127.5 - 1;
|
||
floatData[subOffset + 2] = reader.getUint8() / 127.5 - 1;
|
||
floatData[subOffset + 3] = reader.getUint8() / 127.5 - 1;
|
||
verOffset += 16;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
reader.pos = lastPosition;
|
||
break;
|
||
}
|
||
var vertexBuffer = new VertexBuffer3D(vertexData.byteLength, gl.STATIC_DRAW, true);
|
||
vertexBuffer.vertexDeclaration = vertexDeclaration;
|
||
vertexBuffer.setData(vertexData);
|
||
var vertexCount = vertexBuffer._byteLength / vertexDeclaration.vertexStride;
|
||
if (vertexCount > 65535)
|
||
mesh._indexFormat = exports.IndexFormat.UInt32;
|
||
else
|
||
mesh._indexFormat = exports.IndexFormat.UInt16;
|
||
mesh._vertexBuffer = vertexBuffer;
|
||
mesh._vertexCount += vertexCount;
|
||
memorySize += floatData.length * 4;
|
||
}
|
||
var ibStart = offset + reader.getUint32();
|
||
var ibLength = reader.getUint32();
|
||
var ibDatas;
|
||
if (mesh.indexFormat == exports.IndexFormat.UInt32)
|
||
ibDatas = new Uint32Array(arrayBuffer.slice(ibStart, ibStart + ibLength));
|
||
else
|
||
ibDatas = new Uint16Array(arrayBuffer.slice(ibStart, ibStart + ibLength));
|
||
var indexBuffer = new IndexBuffer3D(mesh.indexFormat, ibDatas.length, gl.STATIC_DRAW, true);
|
||
indexBuffer.setData(ibDatas);
|
||
mesh._indexBuffer = indexBuffer;
|
||
mesh._setBuffer(mesh._vertexBuffer, indexBuffer);
|
||
memorySize += indexBuffer.indexCount * 2;
|
||
mesh._setCPUMemory(memorySize);
|
||
mesh._setGPUMemory(memorySize);
|
||
if (LoadModelV05._version == "LAYAMODEL:0501" || LoadModelV05._version == "LAYAMODEL:COMPRESSION_0501") {
|
||
var bounds = mesh.bounds;
|
||
var min = bounds.getMin();
|
||
var max = bounds.getMax();
|
||
min.setValue(reader.getFloat32(), reader.getFloat32(), reader.getFloat32());
|
||
max.setValue(reader.getFloat32(), reader.getFloat32(), reader.getFloat32());
|
||
bounds.setMin(min);
|
||
bounds.setMax(max);
|
||
mesh.bounds = bounds;
|
||
}
|
||
var boneNames = mesh._boneNames = [];
|
||
var boneCount = reader.getUint16();
|
||
boneNames.length = boneCount;
|
||
for (i = 0; i < boneCount; i++)
|
||
boneNames[i] = LoadModelV05._strings[reader.getUint16()];
|
||
var bindPoseDataStart = reader.getUint32();
|
||
var bindPoseDataLength = reader.getUint32();
|
||
var bindPoseDatas = new Float32Array(arrayBuffer.slice(offset + bindPoseDataStart, offset + bindPoseDataStart + bindPoseDataLength));
|
||
var bindPoseFloatCount = bindPoseDatas.length;
|
||
var bindPoseBuffer = mesh._inverseBindPosesBuffer = new ArrayBuffer(bindPoseFloatCount * 4);
|
||
mesh._inverseBindPoses = [];
|
||
if (bindPoseFloatCount != 0)
|
||
mesh._instanceBufferStateType = Mesh.MESH_INSTANCEBUFFER_TYPE_SIMPLEANIMATOR;
|
||
else
|
||
mesh._instanceBufferStateType = Mesh.MESH_INSTANCEBUFFER_TYPE_NORMAL;
|
||
mesh._setInstanceBuffer(mesh._instanceBufferStateType);
|
||
for (i = 0; i < bindPoseFloatCount; i += 16) {
|
||
var inverseGlobalBindPose = new Matrix4x4(bindPoseDatas[i + 0], bindPoseDatas[i + 1], bindPoseDatas[i + 2], bindPoseDatas[i + 3], bindPoseDatas[i + 4], bindPoseDatas[i + 5], bindPoseDatas[i + 6], bindPoseDatas[i + 7], bindPoseDatas[i + 8], bindPoseDatas[i + 9], bindPoseDatas[i + 10], bindPoseDatas[i + 11], bindPoseDatas[i + 12], bindPoseDatas[i + 13], bindPoseDatas[i + 14], bindPoseDatas[i + 15], new Float32Array(bindPoseBuffer, i * 4, 16));
|
||
mesh._inverseBindPoses[i / 16] = inverseGlobalBindPose;
|
||
}
|
||
return true;
|
||
}
|
||
static READ_SUBMESH() {
|
||
var reader = LoadModelV05._readData;
|
||
var arrayBuffer = reader.__getBuffer();
|
||
var subMesh = new SubMesh(LoadModelV05._mesh);
|
||
reader.getInt16();
|
||
var ibStart = reader.getUint32();
|
||
var ibCount = reader.getUint32();
|
||
var indexBuffer = LoadModelV05._mesh._indexBuffer;
|
||
subMesh._indexBuffer = indexBuffer;
|
||
subMesh._setIndexRange(ibStart, ibCount);
|
||
var vertexBuffer = LoadModelV05._mesh._vertexBuffer;
|
||
subMesh._vertexBuffer = vertexBuffer;
|
||
var offset = LoadModelV05._DATA.offset;
|
||
var subIndexBufferStart = subMesh._subIndexBufferStart;
|
||
var subIndexBufferCount = subMesh._subIndexBufferCount;
|
||
var boneIndicesList = subMesh._boneIndicesList;
|
||
var drawCount = reader.getUint16();
|
||
subIndexBufferStart.length = drawCount;
|
||
subIndexBufferCount.length = drawCount;
|
||
boneIndicesList.length = drawCount;
|
||
var skinnedCache = LoadModelV05._mesh._skinnedMatrixCaches;
|
||
var subMeshIndex = LoadModelV05._subMeshes.length;
|
||
skinnedCache.length = LoadModelV05._mesh._inverseBindPoses.length;
|
||
for (var i = 0; i < drawCount; i++) {
|
||
subIndexBufferStart[i] = reader.getUint32();
|
||
subIndexBufferCount[i] = reader.getUint32();
|
||
var boneDicofs = reader.getUint32();
|
||
var boneDicCount = reader.getUint32();
|
||
var boneIndices = boneIndicesList[i] = new Uint16Array(arrayBuffer.slice(offset + boneDicofs, offset + boneDicofs + boneDicCount));
|
||
for (var j = 0, m = boneIndices.length; j < m; j++) {
|
||
var index = boneIndices[j];
|
||
skinnedCache[index] || (skinnedCache[index] = new skinnedMatrixCache(subMeshIndex, i, j));
|
||
}
|
||
}
|
||
LoadModelV05._subMeshes.push(subMesh);
|
||
return true;
|
||
}
|
||
}
|
||
LoadModelV05._BLOCK = { count: 0 };
|
||
LoadModelV05._DATA = { offset: 0, size: 0 };
|
||
LoadModelV05._strings = [];
|
||
|
||
class MeshReader {
|
||
static _parse(data, propertyParams = null, constructParams = null) {
|
||
var mesh = new Mesh();
|
||
MeshReader.read(data, mesh, mesh._subMeshes);
|
||
return mesh;
|
||
}
|
||
static read(data, mesh, subMeshes) {
|
||
var readData = new Laya.Byte(data);
|
||
readData.pos = 0;
|
||
var version = readData.readUTFString();
|
||
switch (version) {
|
||
case "LAYAMODEL:0301":
|
||
case "LAYAMODEL:0400":
|
||
case "LAYAMODEL:0401":
|
||
LoadModelV04.parse(readData, version, mesh, subMeshes);
|
||
break;
|
||
case "LAYAMODEL:05":
|
||
case "LAYAMODEL:COMPRESSION_05":
|
||
case "LAYAMODEL:0501":
|
||
case "LAYAMODEL:COMPRESSION_0501":
|
||
LoadModelV05.parse(readData, version, mesh, subMeshes);
|
||
break;
|
||
default:
|
||
throw new Error("MeshReader: unknown mesh version.");
|
||
}
|
||
mesh._setSubMeshes(subMeshes);
|
||
if (version != "LAYAMODEL:0501" && version != "LAYAMODEL:COMPRESSION_0501")
|
||
mesh.calculateBounds();
|
||
}
|
||
}
|
||
|
||
var SkyPanoramicFS = "#if defined(GL_FRAGMENT_PRECISION_HIGH)// 原来的写法会被我们自己的解析流程处理,而我们的解析是不认内置宏的,导致被删掉,所以改成 if defined 了\r\n\tprecision highp float;\r\n#else\r\n\tprecision mediump float;\r\n#endif\r\n\r\n#define PI 3.14159265359\r\n#include \"Lighting.glsl\";\r\n\r\nuniform sampler2D u_Texture;\r\nuniform vec4 u_TextureHDRParams;\r\nuniform vec4 u_TintColor;\r\n\r\nvarying vec3 v_Texcoord;\r\nvarying vec2 v_Image180ScaleAndCutoff;\r\nvarying vec4 v_Layout3DScaleAndOffset;\r\n\r\nvec2 ToRadialCoords(vec3 coords)\r\n{\r\n\tvec3 normalizedCoords = normalize(coords);\r\n\tfloat latitude = acos(normalizedCoords.y);\r\n\tfloat longitude = atan(normalizedCoords.z,normalizedCoords.x);\r\n\tvec2 sphereCoords = vec2(longitude, latitude) * vec2(0.5/PI, 1.0/PI);\r\n\treturn vec2(0.5,1.0) - sphereCoords;\r\n}\r\n\r\n\r\nvoid main()\r\n{\t\r\n\tvec2 tc = ToRadialCoords(v_Texcoord);\r\n\tif (tc.x > v_Image180ScaleAndCutoff.y)\r\n\t\tgl_FragColor=vec4(0,0,0,1);\r\n\ttc.x = mod(tc.x*v_Image180ScaleAndCutoff.x, 1.0);\r\n\ttc = (tc + v_Layout3DScaleAndOffset.xy) * v_Layout3DScaleAndOffset.zw;\r\n\r\n\tmediump vec4 tex = texture2D (u_Texture, tc);\r\n\tmediump vec3 c = decodeHDR (tex, u_TextureHDRParams.x);\r\n\tc = c * u_TintColor.rgb * 2.0;//Gamma Space is 2.0,linear space is 4.59479380\r\n\tgl_FragColor=vec4(c, 1.0);\r\n}\r\n\r\n";
|
||
|
||
var SkyPanoramicVS = "#include \"Lighting.glsl\";\r\n\r\n#define PI 3.14159265359\r\n\r\nattribute vec4 a_Position;\r\n\r\nuniform mat4 u_ViewProjection;\r\nuniform float u_Rotation;\r\n\r\nvarying vec3 v_Texcoord;\r\nvarying vec2 v_Image180ScaleAndCutoff;\r\nvarying vec4 v_Layout3DScaleAndOffset;\r\n\r\nvec4 rotateAroundYInDegrees (vec4 vertex, float degrees)\r\n{\r\n\tfloat angle = degrees * PI / 180.0;\r\n\tfloat sina=sin(angle);\r\n\tfloat cosa=cos(angle);\r\n\tmat2 m = mat2(cosa, -sina, sina, cosa);\r\n\treturn vec4(m*vertex.xz, vertex.yw).xzyw;\r\n}\r\n\r\n\t\t\r\nvoid main()\r\n{\r\n\tvec4 position = rotateAroundYInDegrees(a_Position, u_Rotation);\r\n\tgl_Position = u_ViewProjection*position;\r\n\r\n\tv_Texcoord=vec3(-a_Position.x,-a_Position.y,a_Position.z);// NOTE: -a_Position.x convert coords system\r\n\r\n\t// Calculate constant horizontal scale and cutoff for 180 (vs 360) image type\r\n\tv_Image180ScaleAndCutoff = vec2(1.0, 1.0);// 360 degree mode\r\n\r\n\t// Calculate constant scale and offset for 3D layouts\r\n\tv_Layout3DScaleAndOffset = vec4(0,0,1,1);\r\n}\r\n";
|
||
|
||
class SkyPanoramicMaterial extends Material {
|
||
constructor() {
|
||
super();
|
||
this._exposure = 1.0;
|
||
this._textureDecodeFormat = Laya.TextureDecodeFormat.Normal;
|
||
this._textureHDRParams = new Vector4(1.0, 0.0, 0.0, 1.0);
|
||
this.setShaderName("SkyPanoramic");
|
||
var shaderValues = this._shaderValues;
|
||
shaderValues.setVector(SkyPanoramicMaterial.TINTCOLOR, new Vector4(0.5, 0.5, 0.5, 0.5));
|
||
shaderValues.setNumber(SkyPanoramicMaterial.ROTATION, 0.0);
|
||
shaderValues.setVector(SkyPanoramicMaterial.TEXTURE_HDR_PARAMS, this._textureHDRParams);
|
||
}
|
||
static __init__() {
|
||
var attributeMap = {
|
||
'a_Position': VertexMesh.MESH_POSITION0
|
||
};
|
||
var uniformMap = {
|
||
'u_TintColor': Shader3D.PERIOD_MATERIAL,
|
||
'u_TextureHDRParams': Shader3D.PERIOD_MATERIAL,
|
||
'u_Rotation': Shader3D.PERIOD_MATERIAL,
|
||
'u_Texture': Shader3D.PERIOD_MATERIAL,
|
||
'u_ViewProjection': Shader3D.PERIOD_CAMERA
|
||
};
|
||
var shader = Shader3D.add("SkyPanoramic");
|
||
var subShader = new SubShader(attributeMap, uniformMap);
|
||
shader.addSubShader(subShader);
|
||
subShader.addShaderPass(SkyPanoramicVS, SkyPanoramicFS);
|
||
}
|
||
get tintColor() {
|
||
return this._shaderValues.getVector(SkyPanoramicMaterial.TINTCOLOR);
|
||
}
|
||
set tintColor(value) {
|
||
this._shaderValues.setVector(SkyPanoramicMaterial.TINTCOLOR, value);
|
||
}
|
||
get exposure() {
|
||
return this._exposure;
|
||
}
|
||
set exposure(value) {
|
||
if (this._exposure !== value) {
|
||
this._exposure = value;
|
||
if (this._textureDecodeFormat == Laya.TextureDecodeFormat.RGBM)
|
||
this._textureHDRParams.x = value * Laya.BaseTexture._rgbmRange;
|
||
else
|
||
this._textureHDRParams.x = value;
|
||
}
|
||
}
|
||
get rotation() {
|
||
return this._shaderValues.getNumber(SkyPanoramicMaterial.ROTATION);
|
||
}
|
||
set rotation(value) {
|
||
this._shaderValues.setNumber(SkyPanoramicMaterial.ROTATION, value);
|
||
}
|
||
get panoramicTexture() {
|
||
return this._shaderValues.getTexture(SkyPanoramicMaterial.TEXTURE);
|
||
}
|
||
set panoramicTexture(value) {
|
||
this._shaderValues.setTexture(SkyPanoramicMaterial.TEXTURE, value);
|
||
}
|
||
get panoramicTextureDecodeFormat() {
|
||
return this._textureDecodeFormat;
|
||
}
|
||
set panoramicTextureDecodeFormat(value) {
|
||
if (this._textureDecodeFormat !== value) {
|
||
this._textureDecodeFormat = value;
|
||
if (value == Laya.TextureDecodeFormat.RGBM)
|
||
this._textureHDRParams.x = this._exposure * Laya.BaseTexture._rgbmRange;
|
||
else
|
||
this._textureHDRParams.x = this._exposure;
|
||
}
|
||
}
|
||
}
|
||
SkyPanoramicMaterial.TINTCOLOR = Shader3D.propertyNameToID("u_TintColor");
|
||
SkyPanoramicMaterial.EXPOSURE = Shader3D.propertyNameToID("u_Exposure");
|
||
SkyPanoramicMaterial.ROTATION = Shader3D.propertyNameToID("u_Rotation");
|
||
SkyPanoramicMaterial.TEXTURE = Shader3D.propertyNameToID("u_Texture");
|
||
SkyPanoramicMaterial.TEXTURE_HDR_PARAMS = Shader3D.propertyNameToID("u_TextureHDRParams");
|
||
|
||
class Laya3D {
|
||
constructor() {
|
||
}
|
||
static get enablePhysics() {
|
||
return Physics3D._enablePhysics;
|
||
}
|
||
static _cancelLoadByUrl(url) {
|
||
Laya.Laya.loader.cancelLoadByUrl(url);
|
||
Laya3D._innerFirstLevelLoaderManager.cancelLoadByUrl(url);
|
||
Laya3D._innerSecondLevelLoaderManager.cancelLoadByUrl(url);
|
||
Laya3D._innerThirdLevelLoaderManager.cancelLoadByUrl(url);
|
||
Laya3D._innerFourthLevelLoaderManager.cancelLoadByUrl(url);
|
||
}
|
||
static _changeWebGLSize(width, height) {
|
||
Laya.WebGL.onStageResize(width, height);
|
||
RenderContext3D.clientWidth = width;
|
||
RenderContext3D.clientHeight = height;
|
||
}
|
||
static __init__(width, height, config) {
|
||
Laya.Config.isAntialias = config.isAntialias;
|
||
Laya.Config.isAlpha = config.isAlpha;
|
||
Laya.Config.premultipliedAlpha = config.premultipliedAlpha;
|
||
Laya.Config.isStencil = config.isStencil;
|
||
if (!Laya.WebGL.enable()) {
|
||
alert("Laya3D init error,must support webGL!");
|
||
return;
|
||
}
|
||
Laya.RunDriver.changeWebGLSize = Laya3D._changeWebGLSize;
|
||
Laya.Render.is3DMode = true;
|
||
Laya.Laya.init(width, height);
|
||
if (!Laya.Render.supportWebGLPlusRendering) {
|
||
Laya.LayaGL.instance = Laya.WebGLContext.mainContext;
|
||
Laya.LayaGL.instance.createCommandEncoder = function (reserveSize = 128, adjustSize = 64, isSyncToRenderThread = false) {
|
||
return new Laya.CommandEncoder(this, reserveSize, adjustSize, isSyncToRenderThread);
|
||
};
|
||
}
|
||
config._multiLighting = config.enableMultiLight && Laya.SystemUtils.supportTextureFormat(Laya.TextureFormat.R32G32B32A32);
|
||
ILaya3D.Shader3D = Shader3D;
|
||
ILaya3D.Scene3D = Scene3D;
|
||
ILaya3D.MeshRenderStaticBatchManager = MeshRenderStaticBatchManager;
|
||
ILaya3D.MeshRenderDynamicBatchManager = MeshRenderDynamicBatchManager;
|
||
ILaya3D.SubMeshDynamicBatch = SubMeshDynamicBatch;
|
||
ILaya3D.Laya3D = Laya3D;
|
||
ILaya3D.Matrix4x4 = Matrix4x4;
|
||
ILaya3D.Physics3D = Physics3D;
|
||
ILaya3D.ShadowLightType = exports.ShadowLightType;
|
||
ILaya3D.Camera = Camera;
|
||
ILaya3D.CommandBuffer = CommandBuffer;
|
||
ILaya3D.RenderElement = RenderElement;
|
||
ILaya3D.SubMeshRenderElement = SubMeshRenderElement;
|
||
Laya3D.enableNative3D();
|
||
if (config.isUseCannonPhysicsEngine)
|
||
Physics3D.__cannoninit__();
|
||
Physics3D.__bulletinit__();
|
||
VertexElementFormat.__init__();
|
||
VertexMesh.__init__();
|
||
VertexShurikenParticleBillboard.__init__();
|
||
VertexShurikenParticleMesh.__init__();
|
||
VertexPositionTexture0.__init__();
|
||
VertexTrail.__init__();
|
||
VertexPositionTerrain.__init__();
|
||
PixelLineVertex.__init__();
|
||
SubMeshInstanceBatch.__init__();
|
||
SubMeshDynamicBatch.__init__();
|
||
ShaderInit3D.__init__();
|
||
ShadowUtils.init();
|
||
PBRMaterial.__init__();
|
||
PBRStandardMaterial.__init__();
|
||
PBRSpecularMaterial.__init__();
|
||
SkyPanoramicMaterial.__init__();
|
||
Mesh.__init__();
|
||
PrimitiveMesh.__init__();
|
||
Sprite3D.__init__();
|
||
RenderableSprite3D.__init__();
|
||
MeshSprite3D.__init__();
|
||
SkinnedMeshSprite3D.__init__();
|
||
SimpleSkinnedMeshSprite3D.__init__();
|
||
ShuriKenParticle3D.__init__();
|
||
TrailSprite3D.__init__();
|
||
PostProcess.__init__();
|
||
Scene3D.__init__();
|
||
MeshRenderStaticBatchManager.__init__();
|
||
Material.__initDefine__();
|
||
BaseMaterial.__initDefine__();
|
||
BlinnPhongMaterial.__initDefine__();
|
||
SkyProceduralMaterial.__initDefine__();
|
||
UnlitMaterial.__initDefine__();
|
||
TrailMaterial.__initDefine__();
|
||
EffectMaterial.__initDefine__();
|
||
WaterPrimaryMaterial.__initDefine__();
|
||
ShurikenParticleMaterial.__initDefine__();
|
||
ExtendTerrainMaterial.__initDefine__();
|
||
PixelLineMaterial.__initDefine__();
|
||
SkyBoxMaterial.__initDefine__();
|
||
Command.__init__();
|
||
Laya.ClassUtils.regClass("Laya.SkyPanoramicMaterial", SkyPanoramicMaterial);
|
||
Laya.ClassUtils.regClass("Laya.EffectMaterial", EffectMaterial);
|
||
Laya.ClassUtils.regClass("Laya.UnlitMaterial", UnlitMaterial);
|
||
Laya.ClassUtils.regClass("Laya.BlinnPhongMaterial", BlinnPhongMaterial);
|
||
Laya.ClassUtils.regClass("Laya.SkyProceduralMaterial", SkyProceduralMaterial);
|
||
Laya.ClassUtils.regClass("Laya.PBRStandardMaterial", PBRStandardMaterial);
|
||
Laya.ClassUtils.regClass("Laya.PBRSpecularMaterial", PBRSpecularMaterial);
|
||
Laya.ClassUtils.regClass("Laya.SkyBoxMaterial", SkyBoxMaterial);
|
||
Laya.ClassUtils.regClass("Laya.WaterPrimaryMaterial", WaterPrimaryMaterial);
|
||
Laya.ClassUtils.regClass("Laya.ExtendTerrainMaterial", ExtendTerrainMaterial);
|
||
Laya.ClassUtils.regClass("Laya.ShurikenParticleMaterial", ShurikenParticleMaterial);
|
||
Laya.ClassUtils.regClass("Laya.TrailMaterial", TrailMaterial);
|
||
Laya.ClassUtils.regClass("Laya.PhysicsCollider", Laya.PhysicsCollider);
|
||
Laya.ClassUtils.regClass("Laya.Rigidbody3D", Laya.Rigidbody3D);
|
||
Laya.ClassUtils.regClass("Laya.CharacterController", Laya.CharacterController);
|
||
Laya.ClassUtils.regClass("Laya.Animator", Animator);
|
||
Laya.ClassUtils.regClass("PhysicsCollider", Laya.PhysicsCollider);
|
||
Laya.ClassUtils.regClass("CharacterController", Laya.CharacterController);
|
||
Laya.ClassUtils.regClass("Animator", Animator);
|
||
Laya.ClassUtils.regClass("Rigidbody3D", Laya.Rigidbody3D);
|
||
Laya.ClassUtils.regClass("FixedConstraint", Laya.FixedConstraint);
|
||
Laya.ClassUtils.regClass("ConfigurableConstraint", Laya.ConfigurableConstraint);
|
||
PixelLineMaterial.defaultMaterial = new PixelLineMaterial();
|
||
BlinnPhongMaterial.defaultMaterial = new BlinnPhongMaterial();
|
||
EffectMaterial.defaultMaterial = new EffectMaterial();
|
||
UnlitMaterial.defaultMaterial = new UnlitMaterial();
|
||
ShurikenParticleMaterial.defaultMaterial = new ShurikenParticleMaterial();
|
||
TrailMaterial.defaultMaterial = new TrailMaterial();
|
||
SkyProceduralMaterial.defaultMaterial = new SkyProceduralMaterial();
|
||
SkyBoxMaterial.defaultMaterial = new SkyBoxMaterial();
|
||
WaterPrimaryMaterial.defaultMaterial = new WaterPrimaryMaterial();
|
||
PixelLineMaterial.defaultMaterial.lock = true;
|
||
BlinnPhongMaterial.defaultMaterial.lock = true;
|
||
EffectMaterial.defaultMaterial.lock = true;
|
||
UnlitMaterial.defaultMaterial.lock = true;
|
||
ShurikenParticleMaterial.defaultMaterial.lock = true;
|
||
TrailMaterial.defaultMaterial.lock = true;
|
||
SkyProceduralMaterial.defaultMaterial.lock = true;
|
||
SkyBoxMaterial.defaultMaterial.lock = true;
|
||
WaterPrimaryMaterial.defaultMaterial.lock = true;
|
||
Laya.Texture2D.__init__();
|
||
TextureCube.__init__();
|
||
SkyBox.__init__();
|
||
SkyDome.__init__();
|
||
ScreenQuad.__init__();
|
||
ScreenTriangle.__init__();
|
||
FrustumCulling.__init__();
|
||
Laya.HalfFloatUtils.__init__();
|
||
var createMap = Laya.LoaderManager.createMap;
|
||
createMap["lh"] = [Laya3D.HIERARCHY, Scene3DUtils._parse];
|
||
createMap["ls"] = [Laya3D.HIERARCHY, Scene3DUtils._parseScene];
|
||
createMap["lm"] = [Laya3D.MESH, MeshReader._parse];
|
||
createMap["lmat"] = [Laya3D.MATERIAL, Material._parse];
|
||
createMap["jpg"] = [Laya3D.TEXTURE2D, Laya.Texture2D._parse];
|
||
createMap["jpeg"] = [Laya3D.TEXTURE2D, Laya.Texture2D._parse];
|
||
createMap["bmp"] = [Laya3D.TEXTURE2D, Laya.Texture2D._parse];
|
||
createMap["gif"] = [Laya3D.TEXTURE2D, Laya.Texture2D._parse];
|
||
createMap["png"] = [Laya3D.TEXTURE2D, Laya.Texture2D._parse];
|
||
createMap["dds"] = [Laya3D.TEXTURE2D, Laya.Texture2D._parse];
|
||
createMap["ktx"] = [Laya3D.TEXTURE2D, Laya.Texture2D._parse];
|
||
createMap["pvr"] = [Laya3D.TEXTURE2D, Laya.Texture2D._parse];
|
||
createMap["lani"] = [Laya3D.ANIMATIONCLIP, AnimationClip._parse];
|
||
createMap["lav"] = [Laya3D.AVATAR, Avatar._parse];
|
||
createMap["ltc"] = [Laya3D.TEXTURECUBE, TextureCube._parse];
|
||
createMap["ltcb"] = [Laya3D.TEXTURECUBEBIN, TextureCube._parseBin];
|
||
createMap["ltcb.ls"] = [Laya3D.TEXTURECUBEBIN, TextureCube._parseBin];
|
||
createMap["lanit.ls"] = [Laya3D.TEXTURE2D, Laya.Texture2D._SimpleAnimatorTextureParse];
|
||
var parserMap = Laya.Loader.parserMap;
|
||
parserMap[Laya3D.HIERARCHY] = Laya3D._loadHierarchy;
|
||
parserMap[Laya3D.MESH] = Laya3D._loadMesh;
|
||
parserMap[Laya3D.MATERIAL] = Laya3D._loadMaterial;
|
||
parserMap[Laya3D.TEXTURECUBE] = Laya3D._loadTextureCube;
|
||
parserMap[Laya3D.TEXTURECUBEBIN] = Laya3D._loadTextureCubeBin;
|
||
parserMap[Laya3D.TEXTURE2D] = Laya3D._loadTexture2D;
|
||
parserMap[Laya3D.ANIMATIONCLIP] = Laya3D._loadAnimationClip;
|
||
parserMap[Laya3D.AVATAR] = Laya3D._loadAvatar;
|
||
parserMap[Laya3D.SIMPLEANIMATORBIN] = Laya3D._loadSimpleAnimator;
|
||
Laya3D._innerFirstLevelLoaderManager.on(Laya.Event.ERROR, null, Laya3D._eventLoadManagerError);
|
||
Laya3D._innerSecondLevelLoaderManager.on(Laya.Event.ERROR, null, Laya3D._eventLoadManagerError);
|
||
Laya3D._innerThirdLevelLoaderManager.on(Laya.Event.ERROR, null, Laya3D._eventLoadManagerError);
|
||
Laya3D._innerFourthLevelLoaderManager.on(Laya.Event.ERROR, null, Laya3D._eventLoadManagerError);
|
||
}
|
||
static enableNative3D() {
|
||
var shaderData = ShaderData;
|
||
var shader3D = ShaderInstance;
|
||
if (Laya.Render.supportWebGLPlusRendering) {
|
||
shaderData.prototype._initData = shaderData.prototype._initDataForNative;
|
||
shaderData.prototype.setBool = shaderData.prototype.setBoolForNative;
|
||
shaderData.prototype.getBool = shaderData.prototype.getBoolForNative;
|
||
shaderData.prototype.setInt = shaderData.prototype.setIntForNative;
|
||
shaderData.prototype.getInt = shaderData.prototype.getIntForNative;
|
||
shaderData.prototype.setNumber = shaderData.prototype.setNumberForNative;
|
||
shaderData.prototype.getNumber = shaderData.prototype.getNumberForNative;
|
||
shaderData.prototype.setVector = shaderData.prototype.setVectorForNative;
|
||
shaderData.prototype.getVector = shaderData.prototype.getVectorForNative;
|
||
shaderData.prototype.setVector2 = shaderData.prototype.setVector2ForNative;
|
||
shaderData.prototype.getVector2 = shaderData.prototype.getVector2ForNative;
|
||
shaderData.prototype.setVector3 = shaderData.prototype.setVector3ForNative;
|
||
shaderData.prototype.getVector3 = shaderData.prototype.getVector3ForNative;
|
||
shaderData.prototype.setQuaternion = shaderData.prototype.setQuaternionForNative;
|
||
shaderData.prototype.getQuaternion = shaderData.prototype.getQuaternionForNative;
|
||
shaderData.prototype.setMatrix4x4 = shaderData.prototype.setMatrix4x4ForNative;
|
||
shaderData.prototype.getMatrix4x4 = shaderData.prototype.getMatrix4x4ForNative;
|
||
shaderData.prototype.setBuffer = shaderData.prototype.setBufferForNative;
|
||
shaderData.prototype.getBuffer = shaderData.prototype.getBufferForNative;
|
||
shaderData.prototype.setTexture = shaderData.prototype.setTextureForNative;
|
||
shaderData.prototype.getTexture = shaderData.prototype.getTextureForNative;
|
||
shaderData.prototype.setAttribute = shaderData.prototype.setAttributeForNative;
|
||
shaderData.prototype.getAttribute = shaderData.prototype.getAttributeForNative;
|
||
shaderData.prototype.cloneTo = shaderData.prototype.cloneToForNative;
|
||
shaderData.prototype.getData = shaderData.prototype.getDataForNative;
|
||
shader3D.prototype._uniformMatrix2fv = shader3D.prototype._uniformMatrix2fvForNative;
|
||
shader3D.prototype._uniformMatrix3fv = shader3D.prototype._uniformMatrix3fvForNative;
|
||
shader3D.prototype._uniformMatrix4fv = shader3D.prototype._uniformMatrix4fvForNative;
|
||
Laya.LayaGLRunner.uploadShaderUniforms = Laya.LayaGLRunner.uploadShaderUniformsForNative;
|
||
}
|
||
}
|
||
static formatRelativePath(base, value) {
|
||
var path;
|
||
path = base + value;
|
||
var char1 = value.charAt(0);
|
||
if (char1 === ".") {
|
||
var parts = path.split("/");
|
||
for (var i = 0, len = parts.length; i < len; i++) {
|
||
if (parts[i] == '..') {
|
||
var index = i - 1;
|
||
if (index > 0 && parts[index] !== '..') {
|
||
parts.splice(index, 2);
|
||
i -= 2;
|
||
}
|
||
}
|
||
}
|
||
path = parts.join('/');
|
||
}
|
||
return path;
|
||
}
|
||
static _endLoad(loader, content = null, subResous = null) {
|
||
if (subResous) {
|
||
for (var i = 0, n = subResous.length; i < n; i++) {
|
||
var resou = Laya.Loader.getRes(subResous[i]);
|
||
(resou) && (resou._removeReference());
|
||
}
|
||
}
|
||
loader.endLoad(content);
|
||
}
|
||
static _eventLoadManagerError(msg) {
|
||
Laya.Laya.loader.event(Laya.Event.ERROR, msg);
|
||
}
|
||
static _addHierarchyInnerUrls(urls, urlMap, urlVersion, hierarchyBasePath, path, type, constructParams = null, propertyParams = null) {
|
||
var formatUrl = Laya3D.formatRelativePath(hierarchyBasePath, path);
|
||
(urlVersion) && (formatUrl = formatUrl + urlVersion);
|
||
urls.push({ url: formatUrl, type: type, constructParams: constructParams, propertyParams: propertyParams });
|
||
urlMap.push(formatUrl);
|
||
return formatUrl;
|
||
}
|
||
static _getSprite3DHierarchyInnerUrls(node, firstLevelUrls, secondLevelUrls, thirdLevelUrls, fourthLelUrls, subUrls, urlVersion, hierarchyBasePath) {
|
||
var i, n;
|
||
var props = node.props;
|
||
switch (node.type) {
|
||
case "Scene3D":
|
||
var lightmaps = props.lightmaps;
|
||
for (i = 0, n = lightmaps.length; i < n; i++) {
|
||
var lightMap = lightmaps[i];
|
||
if (lightMap.path) {
|
||
lightMap.path = Laya3D._addHierarchyInnerUrls(fourthLelUrls, subUrls, urlVersion, hierarchyBasePath, lightMap.path, Laya3D.TEXTURE2D, lightMap.constructParams, lightMap.propertyParams);
|
||
}
|
||
else {
|
||
var lightmapColorData = lightMap.color;
|
||
lightmapColorData.path = Laya3D._addHierarchyInnerUrls(fourthLelUrls, subUrls, urlVersion, hierarchyBasePath, lightmapColorData.path, Laya3D.TEXTURE2D, lightmapColorData.constructParams, lightmapColorData.propertyParams);
|
||
var lightmapDirectionData = lightMap.direction;
|
||
if (lightmapDirectionData)
|
||
lightmapDirectionData.path = Laya3D._addHierarchyInnerUrls(fourthLelUrls, subUrls, urlVersion, hierarchyBasePath, lightmapDirectionData.path, Laya3D.TEXTURE2D, lightmapDirectionData.constructParams, lightmapDirectionData.propertyParams);
|
||
}
|
||
}
|
||
var reflectionTextureData = props.reflectionTexture;
|
||
(reflectionTextureData) && (props.reflection = Laya3D._addHierarchyInnerUrls(thirdLevelUrls, subUrls, urlVersion, hierarchyBasePath, reflectionTextureData, Laya3D.TEXTURECUBE));
|
||
var reflectionData = props.reflection;
|
||
(reflectionData) && (props.reflection = Laya3D._addHierarchyInnerUrls(fourthLelUrls, subUrls, urlVersion, hierarchyBasePath, reflectionData, Laya3D.TEXTURECUBEBIN));
|
||
if (props.sky) {
|
||
var skyboxMaterial = props.sky.material;
|
||
(skyboxMaterial) && (skyboxMaterial.path = Laya3D._addHierarchyInnerUrls(secondLevelUrls, subUrls, urlVersion, hierarchyBasePath, skyboxMaterial.path, Laya3D.MATERIAL));
|
||
}
|
||
break;
|
||
case "Camera":
|
||
var skyboxMatData = props.skyboxMaterial;
|
||
(skyboxMatData) && (skyboxMatData.path = Laya3D._addHierarchyInnerUrls(secondLevelUrls, subUrls, urlVersion, hierarchyBasePath, skyboxMatData.path, Laya3D.MATERIAL));
|
||
break;
|
||
case "TrailSprite3D":
|
||
case "MeshSprite3D":
|
||
case "SkinnedMeshSprite3D":
|
||
case "SimpleSkinnedMeshSprite3D":
|
||
var meshPath = props.meshPath;
|
||
(meshPath) && (props.meshPath = Laya3D._addHierarchyInnerUrls(firstLevelUrls, subUrls, urlVersion, hierarchyBasePath, meshPath, Laya3D.MESH));
|
||
var materials = props.materials;
|
||
if (materials)
|
||
for (i = 0, n = materials.length; i < n; i++)
|
||
materials[i].path = Laya3D._addHierarchyInnerUrls(secondLevelUrls, subUrls, urlVersion, hierarchyBasePath, materials[i].path, Laya3D.MATERIAL);
|
||
if (node.type == "SimpleSkinnedMeshSprite3D")
|
||
if (props.animatorTexture)
|
||
props.animatorTexture = Laya3D._addHierarchyInnerUrls(fourthLelUrls, subUrls, urlVersion, hierarchyBasePath, props.animatorTexture, Laya3D.SIMPLEANIMATORBIN);
|
||
break;
|
||
case "ShuriKenParticle3D":
|
||
if (props.main) {
|
||
var resources = props.renderer.resources;
|
||
var mesh = resources.mesh;
|
||
var material = resources.material;
|
||
(mesh) && (resources.mesh = Laya3D._addHierarchyInnerUrls(firstLevelUrls, subUrls, urlVersion, hierarchyBasePath, mesh, Laya3D.MESH));
|
||
(material) && (resources.material = Laya3D._addHierarchyInnerUrls(secondLevelUrls, subUrls, urlVersion, hierarchyBasePath, material, Laya3D.MATERIAL));
|
||
}
|
||
else {
|
||
var parMeshPath = props.meshPath;
|
||
(parMeshPath) && (props.meshPath = Laya3D._addHierarchyInnerUrls(firstLevelUrls, subUrls, urlVersion, hierarchyBasePath, parMeshPath, Laya3D.MESH));
|
||
props.material.path = Laya3D._addHierarchyInnerUrls(secondLevelUrls, subUrls, urlVersion, hierarchyBasePath, props.material.path, Laya3D.MATERIAL);
|
||
}
|
||
break;
|
||
case "Terrain":
|
||
Laya3D._addHierarchyInnerUrls(fourthLelUrls, subUrls, urlVersion, hierarchyBasePath, props.dataPath, Laya3D.TERRAINRES);
|
||
break;
|
||
case "ReflectionProbe":
|
||
var reflection = props.reflection;
|
||
(reflection) && (props.reflection = Laya3D._addHierarchyInnerUrls(firstLevelUrls, subUrls, urlVersion, hierarchyBasePath, reflection, Laya3D.TEXTURECUBEBIN));
|
||
break;
|
||
}
|
||
var components = node.components;
|
||
if (components) {
|
||
for (var k = 0, p = components.length; k < p; k++) {
|
||
var component = components[k];
|
||
switch (component.type) {
|
||
case "Animator":
|
||
var avatarPath = component.avatarPath;
|
||
var avatarData = component.avatar;
|
||
(avatarData) && (avatarData.path = Laya3D._addHierarchyInnerUrls(fourthLelUrls, subUrls, urlVersion, hierarchyBasePath, avatarData.path, Laya3D.AVATAR));
|
||
var clipPaths = component.clipPaths;
|
||
if (!clipPaths) {
|
||
var layersData = component.layers;
|
||
for (i = 0; i < layersData.length; i++) {
|
||
var states = layersData[i].states;
|
||
for (var j = 0, m = states.length; j < m; j++) {
|
||
var clipPath = states[j].clipPath;
|
||
(clipPath) && (states[j].clipPath = Laya3D._addHierarchyInnerUrls(fourthLelUrls, subUrls, urlVersion, hierarchyBasePath, clipPath, Laya3D.ANIMATIONCLIP));
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
for (i = 0, n = clipPaths.length; i < n; i++)
|
||
clipPaths[i] = Laya3D._addHierarchyInnerUrls(fourthLelUrls, subUrls, urlVersion, hierarchyBasePath, clipPaths[i], Laya3D.ANIMATIONCLIP);
|
||
}
|
||
break;
|
||
case "PhysicsCollider":
|
||
case "Rigidbody3D":
|
||
case "CharacterController":
|
||
var shapes = component.shapes;
|
||
for (i = 0; i < shapes.length; i++) {
|
||
var shape = shapes[i];
|
||
if (shape.type === "MeshColliderShape") {
|
||
var mesh = shape.mesh;
|
||
(mesh) && (shape.mesh = Laya3D._addHierarchyInnerUrls(firstLevelUrls, subUrls, urlVersion, hierarchyBasePath, mesh, Laya3D.MESH));
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
var children = node.child;
|
||
for (i = 0, n = children.length; i < n; i++)
|
||
Laya3D._getSprite3DHierarchyInnerUrls(children[i], firstLevelUrls, secondLevelUrls, thirdLevelUrls, fourthLelUrls, subUrls, urlVersion, hierarchyBasePath);
|
||
}
|
||
static _loadHierarchy(loader) {
|
||
loader._originType = loader.type;
|
||
loader.on(Laya.Event.LOADED, null, Laya3D._onHierarchylhLoaded, [loader]);
|
||
loader.load(loader.url, Laya.Loader.JSON, false, null, true);
|
||
}
|
||
static _onHierarchylhLoaded(loader, lhData) {
|
||
var url = loader.url;
|
||
var urlVersion = Utils3D.getURLVerion(url);
|
||
var hierarchyBasePath = Laya.URL.getPath(url);
|
||
var firstLevUrls = [];
|
||
var secondLevUrls = [];
|
||
var thirdLevUrls = [];
|
||
var forthLevUrls = [];
|
||
var subUrls = [];
|
||
Laya3D._getSprite3DHierarchyInnerUrls(lhData.data, firstLevUrls, secondLevUrls, thirdLevUrls, forthLevUrls, subUrls, urlVersion, hierarchyBasePath);
|
||
var urlCount = firstLevUrls.length + secondLevUrls.length + forthLevUrls.length;
|
||
var totalProcessCount = urlCount + 1;
|
||
var weight = 1 / totalProcessCount;
|
||
Laya3D._onProcessChange(loader, 0, weight, 1.0);
|
||
if (forthLevUrls.length > 0) {
|
||
var processCeil = urlCount / totalProcessCount;
|
||
var processHandler = Laya.Handler.create(null, Laya3D._onProcessChange, [loader, weight, processCeil], false);
|
||
Laya3D._innerFourthLevelLoaderManager._create(forthLevUrls, false, Laya.Handler.create(null, Laya3D._onHierarchyInnerForthLevResouLoaded, [loader, processHandler, lhData, subUrls, firstLevUrls, secondLevUrls, thirdLevUrls, weight + processCeil * forthLevUrls.length, processCeil]), processHandler, null, null, null, 1, true);
|
||
}
|
||
else {
|
||
Laya3D._onHierarchyInnerForthLevResouLoaded(loader, null, lhData, subUrls, firstLevUrls, secondLevUrls, thirdLevUrls, weight, processCeil);
|
||
}
|
||
}
|
||
static _onHierarchyInnerForthLevResouLoaded(loader, processHandler, lhData, subUrls, firstLevUrls, secondLevUrls, thirdLevUrls, processOffset, processCeil) {
|
||
(processHandler) && (processHandler.recover());
|
||
if (thirdLevUrls.length > 0) {
|
||
var process = Laya.Handler.create(null, Laya3D._onProcessChange, [loader, processOffset, processCeil], false);
|
||
Laya3D._innerThirdLevelLoaderManager._create(thirdLevUrls, false, Laya.Handler.create(null, Laya3D._onHierarchyInnerThirdLevResouLoaded, [loader, process, lhData, subUrls, firstLevUrls, secondLevUrls, processOffset + processCeil * secondLevUrls.length, processCeil]), processHandler, null, null, null, 1, true);
|
||
}
|
||
else {
|
||
Laya3D._onHierarchyInnerThirdLevResouLoaded(loader, null, lhData, subUrls, firstLevUrls, secondLevUrls, processOffset, processCeil);
|
||
}
|
||
}
|
||
static _onHierarchyInnerThirdLevResouLoaded(loader, processHandler, lhData, subUrls, firstLevUrls, secondLevUrls, processOffset, processCeil) {
|
||
(processHandler) && (processHandler.recover());
|
||
if (secondLevUrls.length > 0) {
|
||
var process = Laya.Handler.create(null, Laya3D._onProcessChange, [loader, processOffset, processCeil], false);
|
||
Laya3D._innerSecondLevelLoaderManager._create(secondLevUrls, false, Laya.Handler.create(null, Laya3D._onHierarchyInnerSecondLevResouLoaded, [loader, process, lhData, subUrls, firstLevUrls, processOffset + processCeil * secondLevUrls.length, processCeil]), processHandler, null, null, null, 1, true);
|
||
}
|
||
else {
|
||
Laya3D._onHierarchyInnerSecondLevResouLoaded(loader, null, lhData, subUrls, firstLevUrls, processOffset, processCeil);
|
||
}
|
||
}
|
||
static _onHierarchyInnerSecondLevResouLoaded(loader, processHandler, lhData, subUrls, firstLevUrls, processOffset, processCeil) {
|
||
(processHandler) && (processHandler.recover());
|
||
if (firstLevUrls.length > 0) {
|
||
var process = Laya.Handler.create(null, Laya3D._onProcessChange, [loader, processOffset, processCeil], false);
|
||
Laya3D._innerFirstLevelLoaderManager._create(firstLevUrls, false, Laya.Handler.create(null, Laya3D._onHierarchyInnerFirstLevResouLoaded, [loader, process, lhData, subUrls]), processHandler, null, null, null, 1, true);
|
||
}
|
||
else {
|
||
Laya3D._onHierarchyInnerFirstLevResouLoaded(loader, null, lhData, subUrls);
|
||
}
|
||
}
|
||
static _onHierarchyInnerFirstLevResouLoaded(loader, processHandler, lhData, subUrls) {
|
||
(processHandler) && (processHandler.recover());
|
||
loader._cache = loader._createCache;
|
||
var item = lhData.data.type === "Scene3D" ? Scene3DUtils._parseScene(lhData, loader._propertyParams, loader._constructParams) : Scene3DUtils._parse(lhData, loader._propertyParams, loader._constructParams);
|
||
Laya3D._endLoad(loader, item, subUrls);
|
||
}
|
||
static _loadMesh(loader) {
|
||
loader.on(Laya.Event.LOADED, null, Laya3D._onMeshLmLoaded, [loader]);
|
||
loader.load(loader.url, Laya.Loader.BUFFER, false, null, true);
|
||
}
|
||
static _onMeshLmLoaded(loader, lmData) {
|
||
loader._cache = loader._createCache;
|
||
var mesh = MeshReader._parse(lmData, loader._propertyParams, loader._constructParams);
|
||
Laya3D._endLoad(loader, mesh);
|
||
}
|
||
static _loadMaterial(loader) {
|
||
loader.on(Laya.Event.LOADED, null, Laya3D._onMaterilLmatLoaded, [loader]);
|
||
loader.load(loader.url, Laya.Loader.JSON, false, null, true);
|
||
}
|
||
static _onMaterilLmatLoaded(loader, lmatData) {
|
||
var url = loader.url;
|
||
var urlVersion = Utils3D.getURLVerion(url);
|
||
var materialBasePath = Laya.URL.getPath(url);
|
||
var urls = [];
|
||
var subUrls = [];
|
||
var customProps = lmatData.customProps;
|
||
var formatSubUrl;
|
||
var version = lmatData.version;
|
||
switch (version) {
|
||
case "LAYAMATERIAL:01":
|
||
case "LAYAMATERIAL:02":
|
||
case "LAYAMATERIAL:03":
|
||
var i, n;
|
||
var textures = lmatData.props.textures;
|
||
if (textures) {
|
||
for (i = 0, n = textures.length; i < n; i++) {
|
||
var tex2D = textures[i];
|
||
var tex2DPath = tex2D.path;
|
||
if (tex2DPath) {
|
||
formatSubUrl = Laya3D.formatRelativePath(materialBasePath, tex2DPath);
|
||
(urlVersion) && (formatSubUrl = formatSubUrl + urlVersion);
|
||
urls.push({ url: formatSubUrl, constructParams: tex2D.constructParams, propertyParams: tex2D.propertyParams });
|
||
subUrls.push(formatSubUrl);
|
||
tex2D.path = formatSubUrl;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
default:
|
||
throw new Error("Laya3D:unkonwn version.");
|
||
}
|
||
var urlCount = urls.length;
|
||
var totalProcessCount = urlCount + 1;
|
||
var lmatWeight = 1 / totalProcessCount;
|
||
Laya3D._onProcessChange(loader, 0, lmatWeight, 1.0);
|
||
if (urlCount > 0) {
|
||
var processHandler = Laya.Handler.create(null, Laya3D._onProcessChange, [loader, lmatWeight, urlCount / totalProcessCount], false);
|
||
Laya3D._innerFourthLevelLoaderManager._create(urls, false, Laya.Handler.create(null, Laya3D._onMateialTexturesLoaded, [loader, processHandler, lmatData, subUrls]), processHandler, null, null, null, 1, true);
|
||
}
|
||
else {
|
||
Laya3D._onMateialTexturesLoaded(loader, null, lmatData, null);
|
||
}
|
||
}
|
||
static _onMateialTexturesLoaded(loader, processHandler, lmatData, subUrls) {
|
||
loader._cache = loader._createCache;
|
||
var mat = Material._parse(lmatData, loader._propertyParams, loader._constructParams);
|
||
Laya3D._endLoad(loader, mat, subUrls);
|
||
(processHandler) && (processHandler.recover());
|
||
}
|
||
static _loadAvatar(loader) {
|
||
loader.on(Laya.Event.LOADED, null, function (data) {
|
||
loader._cache = loader._createCache;
|
||
var avatar = Avatar._parse(data, loader._propertyParams, loader._constructParams);
|
||
Laya3D._endLoad(loader, avatar);
|
||
});
|
||
loader.load(loader.url, Laya.Loader.JSON, false, null, true);
|
||
}
|
||
static _loadSimpleAnimator(loader) {
|
||
loader.on(Laya.Event.LOADED, null, function (data) {
|
||
loader._cache = loader._createCache;
|
||
var texture = Laya.Texture2D._SimpleAnimatorTextureParse(data, loader._propertyParams, loader._constructParams);
|
||
Laya3D._endLoad(loader, texture);
|
||
});
|
||
loader.load(loader.url, Laya.Loader.BUFFER, false, null, true);
|
||
}
|
||
static _loadAnimationClip(loader) {
|
||
loader.on(Laya.Event.LOADED, null, function (data) {
|
||
loader._cache = loader._createCache;
|
||
var clip = AnimationClip._parse(data);
|
||
Laya3D._endLoad(loader, clip);
|
||
});
|
||
loader.load(loader.url, Laya.Loader.BUFFER, false, null, true);
|
||
}
|
||
static _loadTexture2D(loader) {
|
||
var url = loader.url;
|
||
var index = url.lastIndexOf('.') + 1;
|
||
var verIndex = url.indexOf('?');
|
||
var endIndex = verIndex == -1 ? url.length : verIndex;
|
||
var ext = url.substr(index, endIndex - index);
|
||
var type;
|
||
switch (ext) {
|
||
case "jpg":
|
||
case "jpeg":
|
||
case "bmp":
|
||
case "gif":
|
||
case "png":
|
||
type = "nativeimage";
|
||
break;
|
||
case "dds":
|
||
type = Laya.Loader.BUFFER;
|
||
break;
|
||
case "ktx":
|
||
type = Laya.Loader.BUFFER;
|
||
(!loader._constructParams) && (loader._constructParams = []);
|
||
loader._constructParams[2] = Laya.TextureFormat.KTXTEXTURE;
|
||
break;
|
||
case "pvr":
|
||
type = Laya.Loader.BUFFER;
|
||
(!loader._constructParams) && (loader._constructParams = []);
|
||
loader._propertyParams[2] = Laya.TextureFormat.PVRTEXTURE;
|
||
break;
|
||
}
|
||
loader.on(Laya.Event.LOADED, null, function (image) {
|
||
loader._cache = loader._createCache;
|
||
var tex = Laya.Texture2D._parse(image, loader._propertyParams, loader._constructParams);
|
||
Laya3D._endLoad(loader, tex);
|
||
});
|
||
loader.load(loader.url, type, false, null, true);
|
||
}
|
||
static _loadTextureCube(loader) {
|
||
loader.on(Laya.Event.LOADED, null, Laya3D._onTextureCubeLtcLoaded, [loader]);
|
||
loader.load(loader.url, Laya.Loader.JSON, false, null, true);
|
||
}
|
||
static _loadTextureCubeBin(loader) {
|
||
loader.on(Laya.Event.LOADED, null, (data) => {
|
||
loader._cache = loader._createCache;
|
||
var byte = new Laya.Byte(data);
|
||
var version = byte.readUTFString();
|
||
if (version !== "LAYATEXTURECUBE:0000")
|
||
throw "Laya3D:unknow version.";
|
||
var format = byte.readUint8();
|
||
var mipCount = byte.getUint8();
|
||
var size = byte.readUint16();
|
||
var filterMode = byte.getUint8();
|
||
var warpModeU = byte.getUint8();
|
||
var warpModev = byte.getUint8();
|
||
var anisoLevel = byte.getUint8();
|
||
var cubemap = new TextureCube(size, format, mipCount > 1 ? true : false);
|
||
cubemap.filterMode = filterMode;
|
||
cubemap.wrapModeU = warpModeU;
|
||
cubemap.wrapModeV = warpModev;
|
||
cubemap.anisoLevel = anisoLevel;
|
||
var pos = byte.pos;
|
||
var mipSize = size;
|
||
for (var i = 0; i < mipCount; i++) {
|
||
var uint8Arrays = new Array(6);
|
||
var mipPixelLength = mipSize * mipSize * cubemap._getFormatByteCount();
|
||
for (var j = 0; j < 6; j++) {
|
||
uint8Arrays[j] = new Uint8Array(data, pos, mipPixelLength);
|
||
pos += mipPixelLength;
|
||
}
|
||
cubemap.setSixSidePixels(uint8Arrays, i);
|
||
mipSize /= 2;
|
||
}
|
||
Laya3D._endLoad(loader, cubemap);
|
||
});
|
||
loader.load(loader.url, Laya.Loader.BUFFER, false, null, true);
|
||
}
|
||
static _onTextureCubeLtcLoaded(loader, ltcData) {
|
||
var ltcBasePath = Laya.URL.getPath(loader.url);
|
||
var urls = [Laya3D.formatRelativePath(ltcBasePath, ltcData.front), Laya3D.formatRelativePath(ltcBasePath, ltcData.back), Laya3D.formatRelativePath(ltcBasePath, ltcData.left), Laya3D.formatRelativePath(ltcBasePath, ltcData.right), Laya3D.formatRelativePath(ltcBasePath, ltcData.up), Laya3D.formatRelativePath(ltcBasePath, ltcData.down)];
|
||
var ltcWeight = 1.0 / 7.0;
|
||
Laya3D._onProcessChange(loader, 0, ltcWeight, 1.0);
|
||
var processHandler = Laya.Handler.create(null, Laya3D._onProcessChange, [loader, ltcWeight, 6 / 7], false);
|
||
Laya3D._innerFourthLevelLoaderManager.load(urls, Laya.Handler.create(null, Laya3D._onTextureCubeImagesLoaded, [loader, urls, processHandler]), processHandler, "nativeimage");
|
||
}
|
||
static _onTextureCubeImagesLoaded(loader, urls, processHandler) {
|
||
var images = new Array(6);
|
||
for (var i = 0; i < 6; i++)
|
||
images[i] = Laya.Loader.getRes(urls[i]);
|
||
loader._cache = loader._createCache;
|
||
var tex = TextureCube._parse(images, loader._propertyParams, loader._constructParams);
|
||
processHandler.recover();
|
||
for (i = 0; i < 6; i++)
|
||
Laya.Loader.clearRes(urls[i]);
|
||
Laya3D._endLoad(loader, tex);
|
||
}
|
||
static _onProcessChange(loader, offset, weight, process) {
|
||
process = offset + process * weight;
|
||
(process < 1.0) && (loader.event(Laya.Event.PROGRESS, process * 2 / 3 + 1 / 3));
|
||
}
|
||
static init(width, height, config = null, compolete = null) {
|
||
if (Laya3D._isInit) {
|
||
compolete && compolete.run();
|
||
return;
|
||
}
|
||
Laya3D._isInit = true;
|
||
(config) && (config.cloneTo(Config3D._config));
|
||
config = Config3D._config;
|
||
FrustumCulling.debugFrustumCulling = config.debugFrustumCulling;
|
||
Laya3D._editerEnvironment = config._editerEnvironment;
|
||
Scene3D.octreeCulling = config.octreeCulling;
|
||
Scene3D.octreeInitialSize = config.octreeInitialSize;
|
||
Scene3D.octreeInitialCenter = config.octreeInitialCenter;
|
||
Scene3D.octreeMinNodeSize = config.octreeMinNodeSize;
|
||
Scene3D.octreeLooseness = config.octreeLooseness;
|
||
var physics3D = window.Physics3D;
|
||
if (physics3D == null || config.isUseCannonPhysicsEngine) {
|
||
Physics3D._enablePhysics = false;
|
||
Laya3D.__init__(width, height, config);
|
||
compolete && compolete.run();
|
||
}
|
||
else {
|
||
Physics3D._enablePhysics = true;
|
||
physics3D(config.defaultPhysicsMemory * 16, Laya.BulletInteractive._interactive).then(function () {
|
||
Laya3D.__init__(width, height, config);
|
||
compolete && compolete.run();
|
||
});
|
||
}
|
||
}
|
||
}
|
||
Laya3D.HIERARCHY = "HIERARCHY";
|
||
Laya3D.MESH = "MESH";
|
||
Laya3D.MATERIAL = "MATERIAL";
|
||
Laya3D.TEXTURE2D = "TEXTURE2D";
|
||
Laya3D.TEXTURECUBE = "TEXTURECUBE";
|
||
Laya3D.TEXTURECUBEBIN = "TEXTURECUBEBIN";
|
||
Laya3D.ANIMATIONCLIP = "ANIMATIONCLIP";
|
||
Laya3D.AVATAR = "AVATAR";
|
||
Laya3D.TERRAINHEIGHTDATA = "TERRAINHEIGHTDATA";
|
||
Laya3D.TERRAINRES = "TERRAIN";
|
||
Laya3D.SIMPLEANIMATORBIN = "SIMPLEANIMATOR";
|
||
Laya3D._innerFirstLevelLoaderManager = new Laya.LoaderManager();
|
||
Laya3D._innerSecondLevelLoaderManager = new Laya.LoaderManager();
|
||
Laya3D._innerThirdLevelLoaderManager = new Laya.LoaderManager();
|
||
Laya3D._innerFourthLevelLoaderManager = new Laya.LoaderManager();
|
||
Laya3D._isInit = false;
|
||
Laya3D._editerEnvironment = false;
|
||
window.Laya3D = Laya3D;
|
||
|
||
class CastShadowList extends SingletonList {
|
||
constructor() {
|
||
super();
|
||
}
|
||
add(element) {
|
||
var index = element._indexInCastShadowList;
|
||
if (index !== -1)
|
||
throw "CastShadowList:element has in CastShadowList.";
|
||
this._add(element);
|
||
element._indexInCastShadowList = this.length++;
|
||
}
|
||
remove(element) {
|
||
var index = element._indexInCastShadowList;
|
||
this.length--;
|
||
if (index !== this.length) {
|
||
var end = this.elements[this.length];
|
||
this.elements[index] = end;
|
||
end._indexInCastShadowList = index;
|
||
}
|
||
element._indexInCastShadowList = -1;
|
||
}
|
||
}
|
||
|
||
class AnimatorStateScript {
|
||
constructor() {
|
||
}
|
||
onStateEnter() {
|
||
}
|
||
onStateUpdate() {
|
||
}
|
||
onStateExit() {
|
||
}
|
||
}
|
||
|
||
class Script3D extends Laya.Component {
|
||
constructor() {
|
||
super(...arguments);
|
||
this._indexInPool = -1;
|
||
this._enableState = false;
|
||
}
|
||
get isSingleton() {
|
||
return false;
|
||
}
|
||
_checkProcessTriggers() {
|
||
var prototype = Script3D.prototype;
|
||
if (this.onTriggerEnter !== prototype.onTriggerEnter)
|
||
return true;
|
||
if (this.onTriggerStay !== prototype.onTriggerStay)
|
||
return true;
|
||
if (this.onTriggerExit !== prototype.onTriggerExit)
|
||
return true;
|
||
return false;
|
||
}
|
||
_checkProcessCollisions() {
|
||
var prototype = Script3D.prototype;
|
||
if (this.onCollisionEnter !== prototype.onCollisionEnter)
|
||
return true;
|
||
if (this.onCollisionStay !== prototype.onCollisionStay)
|
||
return true;
|
||
if (this.onCollisionExit !== prototype.onCollisionExit)
|
||
return true;
|
||
return false;
|
||
}
|
||
_onAwake() {
|
||
this.onAwake();
|
||
if (this.onStart !== Script3D.prototype.onStart)
|
||
Laya.Laya.startTimer.callLater(this, this.onStart);
|
||
}
|
||
_onEnable() {
|
||
if (this._enableState)
|
||
return;
|
||
this.owner._scene._addScript(this);
|
||
this._enableState = true;
|
||
this.onEnable();
|
||
}
|
||
_onDisable() {
|
||
if (!this._enableState || this._indexInPool == -1)
|
||
return;
|
||
this.owner._scene._removeScript(this);
|
||
this.owner.offAllCaller(this);
|
||
this._enableState = false;
|
||
this.onDisable();
|
||
}
|
||
_onDestroy() {
|
||
var scripts = this.owner._scripts;
|
||
scripts.splice(scripts.indexOf(this), 1);
|
||
var sprite = this.owner;
|
||
sprite._needProcessTriggers = false;
|
||
for (var i = 0, n = scripts.length; i < n; i++) {
|
||
if (scripts[i]._checkProcessTriggers()) {
|
||
sprite._needProcessTriggers = true;
|
||
break;
|
||
}
|
||
}
|
||
sprite._needProcessCollisions = false;
|
||
for (i = 0, n = scripts.length; i < n; i++) {
|
||
if (scripts[i]._checkProcessCollisions()) {
|
||
sprite._needProcessCollisions = true;
|
||
break;
|
||
}
|
||
}
|
||
this.onDestroy();
|
||
}
|
||
_isScript() {
|
||
return true;
|
||
}
|
||
_onAdded() {
|
||
var sprite = this.owner;
|
||
var scripts = sprite._scripts;
|
||
scripts || (sprite._scripts = scripts = []);
|
||
scripts.push(this);
|
||
if (!sprite._needProcessCollisions)
|
||
sprite._needProcessCollisions = this._checkProcessCollisions();
|
||
if (!sprite._needProcessTriggers)
|
||
sprite._needProcessTriggers = this._checkProcessTriggers();
|
||
}
|
||
onAwake() {
|
||
}
|
||
onEnable() {
|
||
}
|
||
onStart() {
|
||
}
|
||
onTriggerEnter(other) {
|
||
}
|
||
onTriggerStay(other) {
|
||
}
|
||
onTriggerExit(other) {
|
||
}
|
||
onCollisionEnter(collision) {
|
||
}
|
||
onCollisionStay(collision) {
|
||
}
|
||
onCollisionExit(collision) {
|
||
}
|
||
onJointBreak() {
|
||
}
|
||
onMouseDown() {
|
||
}
|
||
onMouseDrag() {
|
||
}
|
||
onMouseClick() {
|
||
}
|
||
onMouseUp() {
|
||
}
|
||
onMouseEnter() {
|
||
}
|
||
onMouseOver() {
|
||
}
|
||
onMouseOut() {
|
||
}
|
||
onUpdate() {
|
||
}
|
||
onLateUpdate() {
|
||
}
|
||
onPreRender() {
|
||
}
|
||
onPostRender() {
|
||
}
|
||
onDisable() {
|
||
}
|
||
onDestroy() {
|
||
}
|
||
}
|
||
|
||
class HeightMap {
|
||
constructor(width, height, minHeight, maxHeight) {
|
||
this._datas = [];
|
||
this._w = width;
|
||
this._h = height;
|
||
this._minHeight = minHeight;
|
||
this._maxHeight = maxHeight;
|
||
}
|
||
static creatFromMesh(mesh, width, height, outCellSize) {
|
||
var vertices = [];
|
||
var indexs = [];
|
||
var submesheCount = mesh.subMeshCount;
|
||
for (var i = 0; i < submesheCount; i++) {
|
||
var subMesh = mesh.getSubMesh(i);
|
||
var vertexBuffer = subMesh._vertexBuffer;
|
||
var verts = vertexBuffer.getFloat32Data();
|
||
var subMeshVertices = [];
|
||
for (var j = 0; j < verts.length; j += vertexBuffer.vertexDeclaration.vertexStride / 4) {
|
||
var position = new Vector3(verts[j + 0], verts[j + 1], verts[j + 2]);
|
||
subMeshVertices.push(position);
|
||
}
|
||
vertices.push(subMeshVertices);
|
||
var ib = subMesh._indexBuffer;
|
||
indexs.push(ib.getData());
|
||
}
|
||
var bounds = mesh.bounds;
|
||
var minX = bounds.getMin().x;
|
||
var minZ = bounds.getMin().z;
|
||
var maxX = bounds.getMax().x;
|
||
var maxZ = bounds.getMax().z;
|
||
var minY = bounds.getMin().y;
|
||
var maxY = bounds.getMax().y;
|
||
var widthSize = maxX - minX;
|
||
var heightSize = maxZ - minZ;
|
||
var cellWidth = outCellSize.x = widthSize / (width - 1);
|
||
var cellHeight = outCellSize.y = heightSize / (height - 1);
|
||
var heightMap = new HeightMap(width, height, minY, maxY);
|
||
var ray = HeightMap._tempRay;
|
||
var rayDir = ray.direction;
|
||
rayDir.x = 0;
|
||
rayDir.y = -1;
|
||
rayDir.z = 0;
|
||
const heightOffset = 0.1;
|
||
var rayY = maxY + heightOffset;
|
||
ray.origin.y = rayY;
|
||
for (var h = 0; h < height; h++) {
|
||
var posZ = minZ + h * cellHeight;
|
||
heightMap._datas[h] = [];
|
||
for (var w = 0; w < width; w++) {
|
||
var posX = minX + w * cellWidth;
|
||
var rayOri = ray.origin;
|
||
rayOri.x = posX;
|
||
rayOri.z = posZ;
|
||
var closestIntersection = HeightMap._getPosition(ray, vertices, indexs);
|
||
heightMap._datas[h][w] = (closestIntersection === Number.MAX_VALUE) ? NaN : rayY - closestIntersection;
|
||
}
|
||
}
|
||
return heightMap;
|
||
}
|
||
static createFromImage(texture, minHeight, maxHeight) {
|
||
var textureWidth = texture.width;
|
||
var textureHeight = texture.height;
|
||
var heightMap = new HeightMap(textureWidth, textureHeight, minHeight, maxHeight);
|
||
var compressionRatio = (maxHeight - minHeight) / 254;
|
||
var pixelsInfo = texture.getPixels();
|
||
var index = 0;
|
||
for (var h = 0; h < textureHeight; h++) {
|
||
var colDatas = heightMap._datas[h] = [];
|
||
for (var w = 0; w < textureWidth; w++) {
|
||
var r = pixelsInfo[index++];
|
||
var g = pixelsInfo[index++];
|
||
var b = pixelsInfo[index++];
|
||
var a = pixelsInfo[index++];
|
||
if (r == 255 && g == 255 && b == 255 && a == 255)
|
||
colDatas[w] = NaN;
|
||
else {
|
||
colDatas[w] = (r + g + b) / 3 * compressionRatio + minHeight;
|
||
}
|
||
}
|
||
}
|
||
return heightMap;
|
||
}
|
||
static _getPosition(ray, vertices, indexs) {
|
||
var closestIntersection = Number.MAX_VALUE;
|
||
for (var i = 0; i < vertices.length; i++) {
|
||
var subMeshVertices = vertices[i];
|
||
var subMeshIndexes = indexs[i];
|
||
for (var j = 0; j < subMeshIndexes.length; j += 3) {
|
||
var vertex1 = subMeshVertices[subMeshIndexes[j + 0]];
|
||
var vertex2 = subMeshVertices[subMeshIndexes[j + 1]];
|
||
var vertex3 = subMeshVertices[subMeshIndexes[j + 2]];
|
||
var intersection = Picker.rayIntersectsTriangle(ray, vertex1, vertex2, vertex3);
|
||
if (!isNaN(intersection) && intersection < closestIntersection) {
|
||
closestIntersection = intersection;
|
||
}
|
||
}
|
||
}
|
||
return closestIntersection;
|
||
}
|
||
get width() {
|
||
return this._w;
|
||
}
|
||
get height() {
|
||
return this._h;
|
||
}
|
||
get maxHeight() {
|
||
return this._maxHeight;
|
||
}
|
||
get minHeight() {
|
||
return this._minHeight;
|
||
}
|
||
_inBounds(row, col) {
|
||
return row >= 0 && row < this._h && col >= 0 && col < this._w;
|
||
}
|
||
getHeight(row, col) {
|
||
if (this._inBounds(row, col))
|
||
return this._datas[row][col];
|
||
else
|
||
return NaN;
|
||
}
|
||
}
|
||
HeightMap._tempRay = new Ray(new Vector3(), new Vector3());
|
||
|
||
class MeshTerrainSprite3D extends MeshSprite3D {
|
||
constructor(mesh, heightMap, name = null) {
|
||
super(mesh, name);
|
||
this._heightMap = heightMap;
|
||
this._cellSize = new Vector2();
|
||
}
|
||
static createFromMesh(mesh, heightMapWidth, heightMapHeight, name = null) {
|
||
var meshTerrainSprite3D = new MeshTerrainSprite3D(mesh, null, name);
|
||
meshTerrainSprite3D._initCreateFromMesh(heightMapWidth, heightMapHeight);
|
||
return meshTerrainSprite3D;
|
||
}
|
||
static createFromMeshAndHeightMap(mesh, texture, minHeight, maxHeight, name = null) {
|
||
var meshTerrainSprite3D = new MeshTerrainSprite3D(mesh, null, name);
|
||
meshTerrainSprite3D._initCreateFromMeshHeightMap(texture, minHeight, maxHeight);
|
||
return meshTerrainSprite3D;
|
||
}
|
||
get minX() {
|
||
var worldMat = this.transform.worldMatrix;
|
||
var worldMatE = worldMat.elements;
|
||
return this._minX * this._getScaleX() + worldMatE[12];
|
||
}
|
||
get minZ() {
|
||
var worldMat = this.transform.worldMatrix;
|
||
var worldMatE = worldMat.elements;
|
||
return this._minZ * this._getScaleZ() + worldMatE[14];
|
||
}
|
||
get width() {
|
||
return (this._heightMap.width - 1) * this._cellSize.x * this._getScaleX();
|
||
}
|
||
get depth() {
|
||
return (this._heightMap.height - 1) * this._cellSize.y * this._getScaleZ();
|
||
}
|
||
_disableRotation() {
|
||
var rotation = this.transform.rotation;
|
||
rotation.x = 0;
|
||
rotation.y = 0;
|
||
rotation.z = 0;
|
||
rotation.w = 1;
|
||
this.transform.rotation = rotation;
|
||
}
|
||
_getScaleX() {
|
||
var worldMat = this.transform.worldMatrix;
|
||
var worldMatE = worldMat.elements;
|
||
var m11 = worldMatE[0];
|
||
var m12 = worldMatE[1];
|
||
var m13 = worldMatE[2];
|
||
return Math.sqrt((m11 * m11) + (m12 * m12) + (m13 * m13));
|
||
}
|
||
_getScaleZ() {
|
||
var worldMat = this.transform.worldMatrix;
|
||
var worldMatE = worldMat.elements;
|
||
var m31 = worldMatE[8];
|
||
var m32 = worldMatE[9];
|
||
var m33 = worldMatE[10];
|
||
return Math.sqrt((m31 * m31) + (m32 * m32) + (m33 * m33));
|
||
}
|
||
_initCreateFromMesh(heightMapWidth, heightMapHeight) {
|
||
this._heightMap = HeightMap.creatFromMesh(this.meshFilter.sharedMesh, heightMapWidth, heightMapHeight, this._cellSize);
|
||
var boundingBox = this.meshFilter.sharedMesh.bounds;
|
||
var min = boundingBox.getMin();
|
||
this._minX = min.x;
|
||
this._minZ = min.z;
|
||
}
|
||
_initCreateFromMeshHeightMap(texture, minHeight, maxHeight) {
|
||
var boundingBox = this.meshFilter.sharedMesh.bounds;
|
||
this._heightMap = HeightMap.createFromImage(texture, minHeight, maxHeight);
|
||
this._computeCellSize(boundingBox);
|
||
var min = boundingBox.getMin();
|
||
this._minX = min.x;
|
||
this._minZ = min.z;
|
||
}
|
||
_computeCellSize(boundingBox) {
|
||
var min = boundingBox.getMin();
|
||
var max = boundingBox.getMax();
|
||
var minX = min.x;
|
||
var minZ = min.z;
|
||
var maxX = max.x;
|
||
var maxZ = max.z;
|
||
var widthSize = maxX - minX;
|
||
var heightSize = maxZ - minZ;
|
||
this._cellSize.x = widthSize / (this._heightMap.width - 1);
|
||
this._cellSize.y = heightSize / (this._heightMap.height - 1);
|
||
}
|
||
_update(state) {
|
||
this._disableRotation();
|
||
}
|
||
getHeight(x, z) {
|
||
MeshTerrainSprite3D._tempVector3.x = x;
|
||
MeshTerrainSprite3D._tempVector3.y = 0;
|
||
MeshTerrainSprite3D._tempVector3.z = z;
|
||
this._disableRotation();
|
||
var worldMat = this.transform.worldMatrix;
|
||
worldMat.invert(MeshTerrainSprite3D._tempMatrix4x4);
|
||
Vector3.transformCoordinate(MeshTerrainSprite3D._tempVector3, MeshTerrainSprite3D._tempMatrix4x4, MeshTerrainSprite3D._tempVector3);
|
||
x = MeshTerrainSprite3D._tempVector3.x;
|
||
z = MeshTerrainSprite3D._tempVector3.z;
|
||
var c = (x - this._minX) / this._cellSize.x;
|
||
var d = (z - this._minZ) / this._cellSize.y;
|
||
var row = Math.floor(d);
|
||
var col = Math.floor(c);
|
||
var s = c - col;
|
||
var t = d - row;
|
||
var uy;
|
||
var vy;
|
||
var worldMatE = worldMat.elements;
|
||
var m21 = worldMatE[4];
|
||
var m22 = worldMatE[5];
|
||
var m23 = worldMatE[6];
|
||
var scaleY = Math.sqrt((m21 * m21) + (m22 * m22) + (m23 * m23));
|
||
var translateY = worldMatE[13];
|
||
var h01 = this._heightMap.getHeight(row, col + 1);
|
||
var h10 = this._heightMap.getHeight((row + 1), col);
|
||
if (isNaN(h01) || isNaN(h10))
|
||
return NaN;
|
||
if (s + t <= 1.0) {
|
||
var h00 = this._heightMap.getHeight(row, col);
|
||
if (isNaN(h00))
|
||
return NaN;
|
||
uy = h01 - h00;
|
||
vy = h10 - h00;
|
||
return (h00 + s * uy + t * vy) * scaleY + translateY;
|
||
}
|
||
else {
|
||
var h11 = this._heightMap.getHeight((row + 1), col + 1);
|
||
if (isNaN(h11))
|
||
return NaN;
|
||
uy = h10 - h11;
|
||
vy = h01 - h11;
|
||
return (h11 + (1.0 - s) * uy + (1.0 - t) * vy) * scaleY + translateY;
|
||
}
|
||
}
|
||
}
|
||
MeshTerrainSprite3D._tempVector3 = new Vector3();
|
||
MeshTerrainSprite3D._tempMatrix4x4 = new Matrix4x4();
|
||
|
||
class GradientDataVector2 {
|
||
constructor() {
|
||
this._currentLength = 0;
|
||
this._elements = new Float32Array(12);
|
||
}
|
||
get gradientCount() {
|
||
return this._currentLength / 3;
|
||
}
|
||
add(key, value) {
|
||
if (this._currentLength < 8) {
|
||
if ((this._currentLength === 6) && ((key !== 1))) {
|
||
key = 1;
|
||
console.log("GradientDataVector2 warning:the forth key is be force set to 1.");
|
||
}
|
||
this._elements[this._currentLength++] = key;
|
||
this._elements[this._currentLength++] = value.x;
|
||
this._elements[this._currentLength++] = value.y;
|
||
}
|
||
else {
|
||
console.log("GradientDataVector2 warning:data count must lessEqual than 4");
|
||
}
|
||
}
|
||
cloneTo(destObject) {
|
||
var destGradientDataVector2 = destObject;
|
||
destGradientDataVector2._currentLength = this._currentLength;
|
||
var destElements = destGradientDataVector2._elements;
|
||
for (var i = 0, n = this._elements.length; i < n; i++) {
|
||
destElements[i] = this._elements[i];
|
||
}
|
||
}
|
||
clone() {
|
||
var destGradientDataVector2 = new GradientDataVector2();
|
||
this.cloneTo(destGradientDataVector2);
|
||
return destGradientDataVector2;
|
||
}
|
||
}
|
||
|
||
class PixelLineData {
|
||
constructor() {
|
||
this.startPosition = new Vector3();
|
||
this.endPosition = new Vector3();
|
||
this.startColor = new Color();
|
||
this.endColor = new Color();
|
||
}
|
||
cloneTo(destObject) {
|
||
this.startPosition.cloneTo(destObject.startPosition);
|
||
this.endPosition.cloneTo(destObject.endPosition);
|
||
this.startColor.cloneTo(destObject.startColor);
|
||
this.endColor.cloneTo(destObject.endColor);
|
||
}
|
||
}
|
||
|
||
class PostProcessEffect {
|
||
constructor() {
|
||
}
|
||
render(context) {
|
||
}
|
||
}
|
||
|
||
class BloomEffect extends PostProcessEffect {
|
||
constructor() {
|
||
super();
|
||
this._shader = null;
|
||
this._shaderData = new ShaderData();
|
||
this._linearColor = new Color();
|
||
this._bloomTextureTexelSize = new Vector4();
|
||
this._shaderThreshold = new Vector4();
|
||
this._shaderParams = new Vector4();
|
||
this._pyramid = null;
|
||
this._intensity = 0.0;
|
||
this._threshold = 1.0;
|
||
this._softKnee = 0.5;
|
||
this._diffusion = 7.0;
|
||
this._anamorphicRatio = 0.0;
|
||
this._dirtIntensity = 0.0;
|
||
this._shaderSetting = new Vector4();
|
||
this._dirtTileOffset = new Vector4();
|
||
this.clamp = 65472.0;
|
||
this.color = new Color(1.0, 1.0, 1.0, 1.0);
|
||
this.fastMode = false;
|
||
this.dirtTexture = null;
|
||
this._shader = Shader3D.find("PostProcessBloom");
|
||
this._pyramid = new Array(BloomEffect.MAXPYRAMIDSIZE * 2);
|
||
}
|
||
get intensity() {
|
||
return this._intensity;
|
||
}
|
||
set intensity(value) {
|
||
this._intensity = Math.max(value, 0.0);
|
||
}
|
||
get threshold() {
|
||
return this._threshold;
|
||
}
|
||
set threshold(value) {
|
||
this._threshold = Math.max(value, 0.0);
|
||
}
|
||
get softKnee() {
|
||
return this._softKnee;
|
||
}
|
||
set softKnee(value) {
|
||
this._softKnee = Math.min(Math.max(value, 0.0), 1.0);
|
||
}
|
||
get diffusion() {
|
||
return this._diffusion;
|
||
}
|
||
set diffusion(value) {
|
||
this._diffusion = Math.min(Math.max(value, 1), 10);
|
||
}
|
||
get anamorphicRatio() {
|
||
return this._anamorphicRatio;
|
||
}
|
||
set anamorphicRatio(value) {
|
||
this._anamorphicRatio = Math.min(Math.max(value, -1.0), 1.0);
|
||
}
|
||
get dirtIntensity() {
|
||
return this._dirtIntensity;
|
||
}
|
||
set dirtIntensity(value) {
|
||
this._dirtIntensity = Math.max(value, 0.0);
|
||
}
|
||
render(context) {
|
||
var cmd = context.command;
|
||
var viewport = context.camera.viewport;
|
||
this._shaderData.setTexture(BloomEffect.SHADERVALUE_AUTOEXPOSURETEX, Laya.Texture2D.whiteTexture);
|
||
var ratio = this._anamorphicRatio;
|
||
var rw = ratio < 0 ? -ratio : 0;
|
||
var rh = ratio > 0 ? ratio : 0;
|
||
var tw = Math.floor(viewport.width / (2 - rw));
|
||
var th = Math.floor(viewport.height / (2 - rh));
|
||
var s = Math.max(tw, th);
|
||
var logs;
|
||
logs = Math.log2(s) + this._diffusion - 10;
|
||
var logsInt = Math.floor(logs);
|
||
var iterations = Math.min(Math.max(logsInt, 1), BloomEffect.MAXPYRAMIDSIZE);
|
||
var sampleScale = 0.5 + logs - logsInt;
|
||
this._shaderData.setNumber(BloomEffect.SHADERVALUE_SAMPLESCALE, sampleScale);
|
||
var lthresh = Color.gammaToLinearSpace(this.threshold);
|
||
var knee = lthresh * this._softKnee + 1e-5;
|
||
this._shaderThreshold.setValue(lthresh, lthresh - knee, knee * 2, 0.25 / knee);
|
||
this._shaderData.setVector(BloomEffect.SHADERVALUE_THRESHOLD, this._shaderThreshold);
|
||
var lclamp = Color.gammaToLinearSpace(this.clamp);
|
||
this._shaderParams.setValue(lclamp, 0, 0, 0);
|
||
this._shaderData.setVector(BloomEffect.SHADERVALUE_PARAMS, this._shaderParams);
|
||
var qualityOffset = this.fastMode ? 1 : 0;
|
||
var lastDownTexture = context.source;
|
||
for (var i = 0; i < iterations; i++) {
|
||
var downIndex = i * 2;
|
||
var upIndex = downIndex + 1;
|
||
var subShader = i == 0 ? BloomEffect.SUBSHADER_PREFILTER13 + qualityOffset : BloomEffect.SUBSHADER_DOWNSAMPLE13 + qualityOffset;
|
||
var mipDownTexture = RenderTexture.createFromPool(tw, th, Laya.RenderTextureFormat.R8G8B8, Laya.RenderTextureDepthFormat.DEPTHSTENCIL_NONE);
|
||
mipDownTexture.filterMode = Laya.FilterMode.Bilinear;
|
||
this._pyramid[downIndex] = mipDownTexture;
|
||
if (i !== iterations - 1) {
|
||
var mipUpTexture = RenderTexture.createFromPool(tw, th, Laya.RenderTextureFormat.R8G8B8, Laya.RenderTextureDepthFormat.DEPTHSTENCIL_NONE);
|
||
mipUpTexture.filterMode = Laya.FilterMode.Bilinear;
|
||
this._pyramid[upIndex] = mipUpTexture;
|
||
}
|
||
cmd.blitScreenTriangle(lastDownTexture, mipDownTexture, null, this._shader, this._shaderData, subShader);
|
||
lastDownTexture = mipDownTexture;
|
||
tw = Math.max(Math.floor(tw / 2), 1);
|
||
th = Math.max(Math.floor(th / 2), 1);
|
||
}
|
||
var lastUpTexture = this._pyramid[(iterations - 1) * 2];
|
||
for (i = iterations - 2; i >= 0; i--) {
|
||
downIndex = i * 2;
|
||
upIndex = downIndex + 1;
|
||
mipDownTexture = this._pyramid[downIndex];
|
||
mipUpTexture = this._pyramid[upIndex];
|
||
cmd.setShaderDataTexture(this._shaderData, BloomEffect.SHADERVALUE_BLOOMTEX, mipDownTexture);
|
||
cmd.blitScreenTriangle(lastUpTexture, mipUpTexture, null, this._shader, this._shaderData, BloomEffect.SUBSHADER_UPSAMPLETENT + qualityOffset);
|
||
lastUpTexture = mipUpTexture;
|
||
}
|
||
var linearColor = this._linearColor;
|
||
this.color.toLinear(linearColor);
|
||
var intensity = Math.pow(2, this._intensity / 10.0) - 1.0;
|
||
var shaderSettings = this._shaderSetting;
|
||
this._shaderSetting.setValue(sampleScale, intensity, this._dirtIntensity, iterations);
|
||
var dirtTexture = this.dirtTexture ? this.dirtTexture : Laya.Texture2D.blackTexture;
|
||
var dirtRatio = dirtTexture.width / dirtTexture.height;
|
||
var screenRatio = viewport.width / viewport.height;
|
||
var dirtTileOffset = this._dirtTileOffset;
|
||
if (dirtRatio > screenRatio)
|
||
dirtTileOffset.setValue(screenRatio / dirtRatio, 1.0, (1.0 - dirtTileOffset.x) * 0.5, 0.0);
|
||
else if (dirtRatio < screenRatio)
|
||
dirtTileOffset.setValue(1.0, dirtRatio / screenRatio, 0.0, (1.0 - dirtTileOffset.y) * 0.5);
|
||
var compositeShaderData = context.compositeShaderData;
|
||
if (this.fastMode)
|
||
compositeShaderData.addDefine(PostProcess.SHADERDEFINE_BLOOM_LOW);
|
||
else
|
||
compositeShaderData.addDefine(PostProcess.SHADERDEFINE_BLOOM);
|
||
this._bloomTextureTexelSize.setValue(1.0 / lastUpTexture.width, 1.0 / lastUpTexture.height, lastUpTexture.width, lastUpTexture.height);
|
||
compositeShaderData.setVector(PostProcess.SHADERVALUE_BLOOM_DIRTTILEOFFSET, dirtTileOffset);
|
||
compositeShaderData.setVector(PostProcess.SHADERVALUE_BLOOM_SETTINGS, shaderSettings);
|
||
compositeShaderData.setVector(PostProcess.SHADERVALUE_BLOOM_COLOR, new Vector4(linearColor.r, linearColor.g, linearColor.b, linearColor.a));
|
||
compositeShaderData.setTexture(PostProcess.SHADERVALUE_BLOOM_DIRTTEX, dirtTexture);
|
||
compositeShaderData.setTexture(PostProcess.SHADERVALUE_BLOOMTEX, lastUpTexture);
|
||
compositeShaderData.setVector(PostProcess.SHADERVALUE_BLOOMTEX_TEXELSIZE, this._bloomTextureTexelSize);
|
||
for (i = 0; i < iterations; i++) {
|
||
downIndex = i * 2;
|
||
upIndex = downIndex + 1;
|
||
RenderTexture.recoverToPool(this._pyramid[downIndex]);
|
||
(i !== 0 && i !== iterations - 1) && (RenderTexture.recoverToPool(this._pyramid[upIndex]));
|
||
}
|
||
context.deferredReleaseTextures.push(lastUpTexture);
|
||
}
|
||
}
|
||
BloomEffect.SHADERVALUE_MAINTEX = Shader3D.propertyNameToID("u_MainTex");
|
||
BloomEffect.SHADERVALUE_AUTOEXPOSURETEX = Shader3D.propertyNameToID("u_AutoExposureTex");
|
||
BloomEffect.SHADERVALUE_SAMPLESCALE = Shader3D.propertyNameToID("u_SampleScale");
|
||
BloomEffect.SHADERVALUE_THRESHOLD = Shader3D.propertyNameToID("u_Threshold");
|
||
BloomEffect.SHADERVALUE_PARAMS = Shader3D.propertyNameToID("u_Params");
|
||
BloomEffect.SHADERVALUE_BLOOMTEX = Shader3D.propertyNameToID("u_BloomTex");
|
||
BloomEffect.SUBSHADER_PREFILTER13 = 0;
|
||
BloomEffect.SUBSHADER_PREFILTER4 = 1;
|
||
BloomEffect.SUBSHADER_DOWNSAMPLE13 = 2;
|
||
BloomEffect.SUBSHADER_DOWNSAMPLE4 = 3;
|
||
BloomEffect.SUBSHADER_UPSAMPLETENT = 4;
|
||
BloomEffect.SUBSHADER_UPSAMPLEBOX = 5;
|
||
BloomEffect.MAXPYRAMIDSIZE = 16;
|
||
|
||
class MaterialInstanceProperty {
|
||
constructor() {
|
||
this._isNeedUpdate = false;
|
||
}
|
||
createInstanceVertexBuffer3D() {
|
||
var gl = Laya.LayaGL.instance;
|
||
this._instanceData = new Float32Array(DrawMeshInstancedCMD.maxInstanceCount * this._vertexStride);
|
||
this._vertexBuffer = new VertexBuffer3D(this._instanceData.length * 4, gl.DYNAMIC_DRAW);
|
||
this._vertexBuffer.vertexDeclaration = this._vertexDeclaration;
|
||
}
|
||
updateVertexBufferData(drawNums) {
|
||
if (!this._isNeedUpdate)
|
||
return;
|
||
let instanceData = this._instanceData;
|
||
let dataValue = this._value;
|
||
let datalength = this._value.length;
|
||
let data;
|
||
let stride = this._vertexStride;
|
||
let updateType = 0;
|
||
if (!(this._value instanceof Float32Array)) {
|
||
updateType = 1;
|
||
}
|
||
switch (updateType) {
|
||
case 0:
|
||
instanceData.set(dataValue, 0);
|
||
break;
|
||
case 1:
|
||
for (let i = 0; i < datalength; i++) {
|
||
data = dataValue[i];
|
||
data.toArray(instanceData, i * stride);
|
||
}
|
||
break;
|
||
}
|
||
this._vertexBuffer.orphanStorage();
|
||
this._vertexBuffer.setData(instanceData.buffer, 0, 0, drawNums * 4 * stride);
|
||
}
|
||
}
|
||
|
||
(function (InstanceLocation) {
|
||
InstanceLocation[InstanceLocation["CUSTOME0"] = 12] = "CUSTOME0";
|
||
InstanceLocation[InstanceLocation["CUSTOME1"] = 13] = "CUSTOME1";
|
||
InstanceLocation[InstanceLocation["CUSTOME2"] = 14] = "CUSTOME2";
|
||
InstanceLocation[InstanceLocation["CUSTOME3"] = 15] = "CUSTOME3";
|
||
})(exports.InstanceLocation || (exports.InstanceLocation = {}));
|
||
class MaterialInstancePropertyBlock {
|
||
constructor() {
|
||
this._type = 0;
|
||
this._propertyMap = {};
|
||
}
|
||
_checkPropertyLegal(vertexElementFormat, propertyName, attributeLocation, prob) {
|
||
var vecDec = prob._vertexDeclaration;
|
||
if (vecDec._vertexElements[0]._elementFormat !== vertexElementFormat)
|
||
throw "Data exists and format does not match";
|
||
if (prob._name !== propertyName)
|
||
throw "You cannot add a new property to an existing attributeLocation,Please use another attributeLocation";
|
||
}
|
||
_creatProperty(attributeName, arrays, vertexStride, vertexformat, attributeLocation) {
|
||
var prob = this._propertyMap[attributeLocation] = new MaterialInstanceProperty();
|
||
prob._name = attributeName;
|
||
prob._value = arrays;
|
||
prob._vertexDeclaration = new VertexDeclaration(vertexStride, [new VertexElement(0, vertexformat, attributeLocation)]);
|
||
prob._isNeedUpdate = true;
|
||
prob._vertexStride = vertexStride / 4;
|
||
prob.createInstanceVertexBuffer3D();
|
||
}
|
||
setVectorArray(attributeName, arrays, attributeLocation) {
|
||
var prob = this._propertyMap[attributeLocation];
|
||
if (prob) {
|
||
this._checkPropertyLegal(VertexElementFormat.Vector4, attributeName, attributeLocation, prob);
|
||
prob._value = arrays;
|
||
prob._isNeedUpdate = true;
|
||
}
|
||
else
|
||
this._creatProperty(attributeName, arrays, 16, VertexElementFormat.Vector4, attributeLocation);
|
||
}
|
||
setVector3Array(attributeName, arrays, attributeLocation) {
|
||
var prob = this._propertyMap[attributeLocation];
|
||
if (prob) {
|
||
this._checkPropertyLegal(VertexElementFormat.Vector3, attributeName, attributeLocation, prob);
|
||
prob._value = arrays;
|
||
prob._isNeedUpdate = true;
|
||
}
|
||
else
|
||
this._creatProperty(attributeName, arrays, 12, VertexElementFormat.Vector3, attributeLocation);
|
||
}
|
||
setVector2Array(attributeName, arrays, attributeLocation) {
|
||
var prob = this._propertyMap[attributeLocation];
|
||
if (prob) {
|
||
this._checkPropertyLegal(VertexElementFormat.Vector2, attributeName, attributeLocation, prob);
|
||
prob._value = arrays;
|
||
prob._isNeedUpdate = true;
|
||
}
|
||
else
|
||
this._creatProperty(attributeName, arrays, 8, VertexElementFormat.Vector2, attributeLocation);
|
||
}
|
||
setNumberArray(attributeName, arrays, attributeLocation) {
|
||
var prob = this._propertyMap[attributeLocation];
|
||
if (prob) {
|
||
this._checkPropertyLegal(VertexElementFormat.Single, attributeName, attributeLocation, prob);
|
||
prob._value = arrays;
|
||
prob._isNeedUpdate = true;
|
||
}
|
||
else
|
||
this._creatProperty(attributeName, arrays, 4, VertexElementFormat.Single, attributeLocation);
|
||
}
|
||
getPropertyArray(attributeLocation) {
|
||
var prob = this._propertyMap[attributeLocation];
|
||
return prob ? prob._value : null;
|
||
}
|
||
clear() {
|
||
this._propertyMap = {};
|
||
}
|
||
}
|
||
MaterialInstancePropertyBlock.INSTANCETYPE_ATTRIBUTE = 0;
|
||
MaterialInstancePropertyBlock.INSTANCETYPE_UNIFORMBUFFER = 1;
|
||
|
||
class ConchVector4 {
|
||
constructor(x = 0, y = 0, z = 0, w = 0) {
|
||
var v = this.elements = new Float32Array(4);
|
||
v[0] = x;
|
||
v[1] = y;
|
||
v[2] = z;
|
||
v[3] = w;
|
||
}
|
||
get x() {
|
||
return this.elements[0];
|
||
}
|
||
set x(value) {
|
||
this.elements[0] = value;
|
||
}
|
||
get y() {
|
||
return this.elements[1];
|
||
}
|
||
set y(value) {
|
||
this.elements[1] = value;
|
||
}
|
||
get z() {
|
||
return this.elements[2];
|
||
}
|
||
set z(value) {
|
||
this.elements[2] = value;
|
||
}
|
||
get w() {
|
||
return this.elements[3];
|
||
}
|
||
set w(value) {
|
||
this.elements[3] = value;
|
||
}
|
||
fromArray(array, offset = 0) {
|
||
this.elements[0] = array[offset + 0];
|
||
this.elements[1] = array[offset + 1];
|
||
this.elements[2] = array[offset + 2];
|
||
this.elements[3] = array[offset + 3];
|
||
}
|
||
cloneTo(destObject) {
|
||
var destVector4 = destObject;
|
||
var destE = destVector4.elements;
|
||
var s = this.elements;
|
||
destE[0] = s[0];
|
||
destE[1] = s[1];
|
||
destE[2] = s[2];
|
||
destE[3] = s[3];
|
||
}
|
||
clone() {
|
||
var destVector4 = new ConchVector4();
|
||
this.cloneTo(destVector4);
|
||
return destVector4;
|
||
}
|
||
static lerp(a, b, t, out) {
|
||
var e = out.elements;
|
||
var f = a.elements;
|
||
var g = b.elements;
|
||
var ax = f[0], ay = f[1], az = f[2], aw = f[3];
|
||
e[0] = ax + t * (g[0] - ax);
|
||
e[1] = ay + t * (g[1] - ay);
|
||
e[2] = az + t * (g[2] - az);
|
||
e[3] = aw + t * (g[3] - aw);
|
||
}
|
||
static transformByM4x4(vector4, m4x4, out) {
|
||
var ve = vector4.elements;
|
||
var vx = ve[0];
|
||
var vy = ve[1];
|
||
var vz = ve[2];
|
||
var vw = ve[3];
|
||
var me = m4x4.elements;
|
||
var oe = out.elements;
|
||
oe[0] = vx * me[0] + vy * me[4] + vz * me[8] + vw * me[12];
|
||
oe[1] = vx * me[1] + vy * me[5] + vz * me[9] + vw * me[13];
|
||
oe[2] = vx * me[2] + vy * me[6] + vz * me[10] + vw * me[14];
|
||
oe[3] = vx * me[3] + vy * me[7] + vz * me[11] + vw * me[15];
|
||
}
|
||
static equals(a, b) {
|
||
var ae = a.elements;
|
||
var be = b.elements;
|
||
return MathUtils3D.nearEqual(Math.abs(ae[0]), Math.abs(be[0])) && MathUtils3D.nearEqual(Math.abs(ae[1]), Math.abs(be[1])) && MathUtils3D.nearEqual(Math.abs(ae[2]), Math.abs(be[2])) && MathUtils3D.nearEqual(Math.abs(ae[3]), Math.abs(be[3]));
|
||
}
|
||
length() {
|
||
return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);
|
||
}
|
||
lengthSquared() {
|
||
return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
|
||
}
|
||
static normalize(s, out) {
|
||
var se = s.elements;
|
||
var oe = out.elements;
|
||
var len = s.length();
|
||
if (len > 0) {
|
||
oe[0] = se[0] * len;
|
||
oe[1] = se[1] * len;
|
||
oe[2] = se[2] * len;
|
||
oe[3] = se[3] * len;
|
||
}
|
||
}
|
||
static add(a, b, out) {
|
||
var oe = out.elements;
|
||
var ae = a.elements;
|
||
var be = b.elements;
|
||
oe[0] = ae[0] + be[0];
|
||
oe[1] = ae[1] + be[1];
|
||
oe[2] = ae[2] + be[2];
|
||
oe[3] = ae[3] + be[3];
|
||
}
|
||
static subtract(a, b, out) {
|
||
var oe = out.elements;
|
||
var ae = a.elements;
|
||
var be = b.elements;
|
||
oe[0] = ae[0] - be[0];
|
||
oe[1] = ae[1] - be[1];
|
||
oe[2] = ae[2] - be[2];
|
||
oe[3] = ae[3] - be[3];
|
||
}
|
||
static multiply(a, b, out) {
|
||
var oe = out.elements;
|
||
var ae = a.elements;
|
||
var be = b.elements;
|
||
oe[0] = ae[0] * be[0];
|
||
oe[1] = ae[1] * be[1];
|
||
oe[2] = ae[2] * be[2];
|
||
oe[3] = ae[3] * be[3];
|
||
}
|
||
static scale(a, b, out) {
|
||
var oe = out.elements;
|
||
var ae = a.elements;
|
||
oe[0] = ae[0] * b;
|
||
oe[1] = ae[1] * b;
|
||
oe[2] = ae[2] * b;
|
||
oe[3] = ae[3] * b;
|
||
}
|
||
static Clamp(value, min, max, out) {
|
||
var valuee = value.elements;
|
||
var x = valuee[0];
|
||
var y = valuee[1];
|
||
var z = valuee[2];
|
||
var w = valuee[3];
|
||
var mine = min.elements;
|
||
var mineX = mine[0];
|
||
var mineY = mine[1];
|
||
var mineZ = mine[2];
|
||
var mineW = mine[3];
|
||
var maxe = max.elements;
|
||
var maxeX = maxe[0];
|
||
var maxeY = maxe[1];
|
||
var maxeZ = maxe[2];
|
||
var maxeW = maxe[3];
|
||
var oute = out.elements;
|
||
x = (x > maxeX) ? maxeX : x;
|
||
x = (x < mineX) ? mineX : x;
|
||
y = (y > maxeY) ? maxeY : y;
|
||
y = (y < mineY) ? mineY : y;
|
||
z = (z > maxeZ) ? maxeZ : z;
|
||
z = (z < mineZ) ? mineZ : z;
|
||
w = (w > maxeW) ? maxeW : w;
|
||
w = (w < mineW) ? mineW : w;
|
||
oute[0] = x;
|
||
oute[1] = y;
|
||
oute[2] = z;
|
||
oute[3] = w;
|
||
}
|
||
static distanceSquared(value1, value2) {
|
||
var value1e = value1.elements;
|
||
var value2e = value2.elements;
|
||
var x = value1e[0] - value2e[0];
|
||
var y = value1e[1] - value2e[1];
|
||
var z = value1e[2] - value2e[2];
|
||
var w = value1e[3] - value2e[3];
|
||
return (x * x) + (y * y) + (z * z) + (w * w);
|
||
}
|
||
static distance(value1, value2) {
|
||
var value1e = value1.elements;
|
||
var value2e = value2.elements;
|
||
var x = value1e[0] - value2e[0];
|
||
var y = value1e[1] - value2e[1];
|
||
var z = value1e[2] - value2e[2];
|
||
var w = value1e[3] - value2e[3];
|
||
return Math.sqrt((x * x) + (y * y) + (z * z) + (w * w));
|
||
}
|
||
static dot(a, b) {
|
||
var ae = a.elements;
|
||
var be = b.elements;
|
||
var r = (ae[0] * be[0]) + (ae[1] * be[1]) + (ae[2] * be[2]) + (ae[3] * be[3]);
|
||
return r;
|
||
}
|
||
static min(a, b, out) {
|
||
var e = out.elements;
|
||
var f = a.elements;
|
||
var g = b.elements;
|
||
e[0] = Math.min(f[0], g[0]);
|
||
e[1] = Math.min(f[1], g[1]);
|
||
e[2] = Math.min(f[2], g[2]);
|
||
e[3] = Math.min(f[3], g[3]);
|
||
}
|
||
static max(a, b, out) {
|
||
var e = out.elements;
|
||
var f = a.elements;
|
||
var g = b.elements;
|
||
e[0] = Math.max(f[0], g[0]);
|
||
e[1] = Math.max(f[1], g[1]);
|
||
e[2] = Math.max(f[2], g[2]);
|
||
e[3] = Math.max(f[3], g[3]);
|
||
}
|
||
}
|
||
ConchVector4.ZERO = new ConchVector4();
|
||
ConchVector4.ONE = new ConchVector4(1.0, 1.0, 1.0, 1.0);
|
||
ConchVector4.UnitX = new ConchVector4(1.0, 0.0, 0.0, 0.0);
|
||
ConchVector4.UnitY = new ConchVector4(0.0, 1.0, 0.0, 0.0);
|
||
ConchVector4.UnitZ = new ConchVector4(0.0, 0.0, 1.0, 0.0);
|
||
ConchVector4.UnitW = new ConchVector4(0.0, 0.0, 0.0, 1.0);
|
||
|
||
class ConchVector3 {
|
||
constructor(x = 0, y = 0, z = 0, nativeElements = null) {
|
||
var v;
|
||
if (nativeElements) {
|
||
v = nativeElements;
|
||
}
|
||
else {
|
||
v = new Float32Array(3);
|
||
}
|
||
this.elements = v;
|
||
v[0] = x;
|
||
v[1] = y;
|
||
v[2] = z;
|
||
}
|
||
static distanceSquared(value1, value2) {
|
||
var value1e = value1.elements;
|
||
var value2e = value2.elements;
|
||
var x = value1e[0] - value2e[0];
|
||
var y = value1e[1] - value2e[1];
|
||
var z = value1e[2] - value2e[2];
|
||
return (x * x) + (y * y) + (z * z);
|
||
}
|
||
static distance(value1, value2) {
|
||
var value1e = value1.elements;
|
||
var value2e = value2.elements;
|
||
var x = value1e[0] - value2e[0];
|
||
var y = value1e[1] - value2e[1];
|
||
var z = value1e[2] - value2e[2];
|
||
return Math.sqrt((x * x) + (y * y) + (z * z));
|
||
}
|
||
static min(a, b, out) {
|
||
var e = out.elements;
|
||
var f = a.elements;
|
||
var g = b.elements;
|
||
e[0] = Math.min(f[0], g[0]);
|
||
e[1] = Math.min(f[1], g[1]);
|
||
e[2] = Math.min(f[2], g[2]);
|
||
}
|
||
static max(a, b, out) {
|
||
var e = out.elements;
|
||
var f = a.elements;
|
||
var g = b.elements;
|
||
e[0] = Math.max(f[0], g[0]);
|
||
e[1] = Math.max(f[1], g[1]);
|
||
e[2] = Math.max(f[2], g[2]);
|
||
}
|
||
static transformQuat(source, rotation, out) {
|
||
var destination = out.elements;
|
||
var se = source.elements;
|
||
var re = rotation.elements;
|
||
var x = se[0], y = se[1], z = se[2], qx = re[0], qy = re[1], qz = re[2], qw = re[3], ix = qw * x + qy * z - qz * y, iy = qw * y + qz * x - qx * z, iz = qw * z + qx * y - qy * x, iw = -qx * x - qy * y - qz * z;
|
||
destination[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
|
||
destination[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
|
||
destination[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
|
||
}
|
||
static scalarLength(a) {
|
||
var f = a.elements;
|
||
var x = f[0], y = f[1], z = f[2];
|
||
return Math.sqrt(x * x + y * y + z * z);
|
||
}
|
||
static scalarLengthSquared(a) {
|
||
var f = a.elements;
|
||
var x = f[0], y = f[1], z = f[2];
|
||
return x * x + y * y + z * z;
|
||
}
|
||
static normalize(s, out) {
|
||
var se = s.elements;
|
||
var oe = out.elements;
|
||
var x = se[0], y = se[1], z = se[2];
|
||
var len = x * x + y * y + z * z;
|
||
if (len > 0) {
|
||
len = 1 / Math.sqrt(len);
|
||
oe[0] = se[0] * len;
|
||
oe[1] = se[1] * len;
|
||
oe[2] = se[2] * len;
|
||
}
|
||
}
|
||
static multiply(a, b, out) {
|
||
var e = out.elements;
|
||
var f = a.elements;
|
||
var g = b.elements;
|
||
e[0] = f[0] * g[0];
|
||
e[1] = f[1] * g[1];
|
||
e[2] = f[2] * g[2];
|
||
}
|
||
static scale(a, b, out) {
|
||
var e = out.elements;
|
||
var f = a.elements;
|
||
e[0] = f[0] * b;
|
||
e[1] = f[1] * b;
|
||
e[2] = f[2] * b;
|
||
}
|
||
static lerp(a, b, t, out) {
|
||
var e = out.elements;
|
||
var f = a.elements;
|
||
var g = b.elements;
|
||
var ax = f[0], ay = f[1], az = f[2];
|
||
e[0] = ax + t * (g[0] - ax);
|
||
e[1] = ay + t * (g[1] - ay);
|
||
e[2] = az + t * (g[2] - az);
|
||
}
|
||
static transformV3ToV3(vector, transform, result) {
|
||
var intermediate = ConchVector3._tempVector4;
|
||
ConchVector3.transformV3ToV4(vector, transform, intermediate);
|
||
var intermediateElem = intermediate.elements;
|
||
var resultElem = result.elements;
|
||
resultElem[0] = intermediateElem[0];
|
||
resultElem[1] = intermediateElem[1];
|
||
resultElem[2] = intermediateElem[2];
|
||
}
|
||
static transformV3ToV4(vector, transform, result) {
|
||
var vectorElem = vector.elements;
|
||
var vectorX = vectorElem[0];
|
||
var vectorY = vectorElem[1];
|
||
var vectorZ = vectorElem[2];
|
||
var transformElem = transform.elements;
|
||
var resultElem = result.elements;
|
||
resultElem[0] = (vectorX * transformElem[0]) + (vectorY * transformElem[4]) + (vectorZ * transformElem[8]) + transformElem[12];
|
||
resultElem[1] = (vectorX * transformElem[1]) + (vectorY * transformElem[5]) + (vectorZ * transformElem[9]) + transformElem[13];
|
||
resultElem[2] = (vectorX * transformElem[2]) + (vectorY * transformElem[6]) + (vectorZ * transformElem[10]) + transformElem[14];
|
||
resultElem[3] = (vectorX * transformElem[3]) + (vectorY * transformElem[7]) + (vectorZ * transformElem[11]) + transformElem[15];
|
||
}
|
||
static TransformNormal(normal, transform, result) {
|
||
var normalElem = normal.elements;
|
||
var normalX = normalElem[0];
|
||
var normalY = normalElem[1];
|
||
var normalZ = normalElem[2];
|
||
var transformElem = transform.elements;
|
||
var resultElem = result.elements;
|
||
resultElem[0] = (normalX * transformElem[0]) + (normalY * transformElem[4]) + (normalZ * transformElem[8]);
|
||
resultElem[1] = (normalX * transformElem[1]) + (normalY * transformElem[5]) + (normalZ * transformElem[9]);
|
||
resultElem[2] = (normalX * transformElem[2]) + (normalY * transformElem[6]) + (normalZ * transformElem[10]);
|
||
}
|
||
static transformCoordinate(coordinate, transform, result) {
|
||
var coordinateElem = coordinate.elements;
|
||
var coordinateX = coordinateElem[0];
|
||
var coordinateY = coordinateElem[1];
|
||
var coordinateZ = coordinateElem[2];
|
||
var transformElem = transform.elements;
|
||
var w = ((coordinateX * transformElem[3]) + (coordinateY * transformElem[7]) + (coordinateZ * transformElem[11]) + transformElem[15]);
|
||
var resultElem = result.elements;
|
||
resultElem[0] = (coordinateX * transformElem[0]) + (coordinateY * transformElem[4]) + (coordinateZ * transformElem[8]) + transformElem[12] / w;
|
||
resultElem[1] = (coordinateX * transformElem[1]) + (coordinateY * transformElem[5]) + (coordinateZ * transformElem[9]) + transformElem[13] / w;
|
||
resultElem[2] = (coordinateX * transformElem[2]) + (coordinateY * transformElem[6]) + (coordinateZ * transformElem[10]) + transformElem[14] / w;
|
||
}
|
||
static Clamp(value, min, max, out) {
|
||
var valuee = value.elements;
|
||
var x = valuee[0];
|
||
var y = valuee[1];
|
||
var z = valuee[2];
|
||
var mine = min.elements;
|
||
var mineX = mine[0];
|
||
var mineY = mine[1];
|
||
var mineZ = mine[2];
|
||
var maxe = max.elements;
|
||
var maxeX = maxe[0];
|
||
var maxeY = maxe[1];
|
||
var maxeZ = maxe[2];
|
||
var oute = out.elements;
|
||
x = (x > maxeX) ? maxeX : x;
|
||
x = (x < mineX) ? mineX : x;
|
||
y = (y > maxeY) ? maxeY : y;
|
||
y = (y < mineY) ? mineY : y;
|
||
z = (z > maxeZ) ? maxeZ : z;
|
||
z = (z < mineZ) ? mineZ : z;
|
||
oute[0] = x;
|
||
oute[1] = y;
|
||
oute[2] = z;
|
||
}
|
||
static add(a, b, out) {
|
||
var e = out.elements;
|
||
var f = a.elements;
|
||
var g = b.elements;
|
||
e[0] = f[0] + g[0];
|
||
e[1] = f[1] + g[1];
|
||
e[2] = f[2] + g[2];
|
||
}
|
||
static subtract(a, b, o) {
|
||
var oe = o.elements;
|
||
var ae = a.elements;
|
||
var be = b.elements;
|
||
oe[0] = ae[0] - be[0];
|
||
oe[1] = ae[1] - be[1];
|
||
oe[2] = ae[2] - be[2];
|
||
}
|
||
static cross(a, b, o) {
|
||
var ae = a.elements;
|
||
var be = b.elements;
|
||
var oe = o.elements;
|
||
var ax = ae[0], ay = ae[1], az = ae[2], bx = be[0], by = be[1], bz = be[2];
|
||
oe[0] = ay * bz - az * by;
|
||
oe[1] = az * bx - ax * bz;
|
||
oe[2] = ax * by - ay * bx;
|
||
}
|
||
static dot(a, b) {
|
||
var ae = a.elements;
|
||
var be = b.elements;
|
||
var r = (ae[0] * be[0]) + (ae[1] * be[1]) + (ae[2] * be[2]);
|
||
return r;
|
||
}
|
||
static equals(a, b) {
|
||
var ae = a.elements;
|
||
var be = b.elements;
|
||
return MathUtils3D.nearEqual(ae[0], be[0]) && MathUtils3D.nearEqual(ae[1], be[1]) && MathUtils3D.nearEqual(ae[2], be[2]);
|
||
}
|
||
get x() {
|
||
return this.elements[0];
|
||
}
|
||
set x(value) {
|
||
this.elements[0] = value;
|
||
}
|
||
get y() {
|
||
return this.elements[1];
|
||
}
|
||
set y(value) {
|
||
this.elements[1] = value;
|
||
}
|
||
get z() {
|
||
return this.elements[2];
|
||
}
|
||
set z(value) {
|
||
this.elements[2] = value;
|
||
}
|
||
setValue(x, y, z) {
|
||
this.elements[0] = x;
|
||
this.elements[1] = y;
|
||
this.elements[2] = z;
|
||
}
|
||
fromArray(array, offset = 0) {
|
||
this.elements[0] = array[offset + 0];
|
||
this.elements[1] = array[offset + 1];
|
||
this.elements[2] = array[offset + 2];
|
||
}
|
||
cloneTo(destObject) {
|
||
var destVector3 = destObject;
|
||
var destE = destVector3.elements;
|
||
var s = this.elements;
|
||
destE[0] = s[0];
|
||
destE[1] = s[1];
|
||
destE[2] = s[2];
|
||
}
|
||
clone() {
|
||
var destVector3 = new ConchVector3();
|
||
this.cloneTo(destVector3);
|
||
return destVector3;
|
||
}
|
||
toDefault() {
|
||
this.elements[0] = 0;
|
||
this.elements[1] = 0;
|
||
this.elements[2] = 0;
|
||
}
|
||
}
|
||
ConchVector3._tempVector4 = new ConchVector4();
|
||
ConchVector3.ZERO = new ConchVector3(0.0, 0.0, 0.0);
|
||
ConchVector3.ONE = new ConchVector3(1.0, 1.0, 1.0);
|
||
ConchVector3.NegativeUnitX = new ConchVector3(-1, 0, 0);
|
||
ConchVector3.UnitX = new ConchVector3(1, 0, 0);
|
||
ConchVector3.UnitY = new ConchVector3(0, 1, 0);
|
||
ConchVector3.UnitZ = new ConchVector3(0, 0, 1);
|
||
ConchVector3.ForwardRH = new ConchVector3(0, 0, -1);
|
||
ConchVector3.ForwardLH = new ConchVector3(0, 0, 1);
|
||
ConchVector3.Up = new ConchVector3(0, 1, 0);
|
||
ConchVector3.NAN = new ConchVector3(NaN, NaN, NaN);
|
||
|
||
class ConchQuaternion {
|
||
constructor(x = 0, y = 0, z = 0, w = 1, nativeElements = null) {
|
||
var v;
|
||
if (nativeElements) {
|
||
v = nativeElements;
|
||
}
|
||
else {
|
||
v = new Float32Array(4);
|
||
}
|
||
v[0] = x;
|
||
v[1] = y;
|
||
v[2] = z;
|
||
v[3] = w;
|
||
this.elements = v;
|
||
}
|
||
static _dotArray(l, r) {
|
||
return l[0] * r[0] + l[1] * r[1] + l[2] * r[2] + l[3] * r[3];
|
||
}
|
||
static _normalizeArray(f, o) {
|
||
var x = f[0], y = f[1], z = f[2], w = f[3];
|
||
var len = x * x + y * y + z * z + w * w;
|
||
if (len > 0) {
|
||
len = 1 / Math.sqrt(len);
|
||
o[0] = x * len;
|
||
o[1] = y * len;
|
||
o[2] = z * len;
|
||
o[3] = w * len;
|
||
}
|
||
}
|
||
static _lerpArray(l, r, amount, o) {
|
||
var inverse = 1.0 - amount;
|
||
if (ConchQuaternion._dotArray(l, r) >= 0) {
|
||
o[0] = (inverse * l[0]) + (amount * r[0]);
|
||
o[1] = (inverse * l[1]) + (amount * r[1]);
|
||
o[2] = (inverse * l[2]) + (amount * r[2]);
|
||
o[3] = (inverse * l[3]) + (amount * r[3]);
|
||
}
|
||
else {
|
||
o[0] = (inverse * l[0]) - (amount * r[0]);
|
||
o[1] = (inverse * l[1]) - (amount * r[1]);
|
||
o[2] = (inverse * l[2]) - (amount * r[2]);
|
||
o[3] = (inverse * l[3]) - (amount * r[3]);
|
||
}
|
||
ConchQuaternion._normalizeArray(o, o);
|
||
}
|
||
static createFromYawPitchRoll(yaw, pitch, roll, out) {
|
||
var halfRoll = roll * 0.5;
|
||
var halfPitch = pitch * 0.5;
|
||
var halfYaw = yaw * 0.5;
|
||
var sinRoll = Math.sin(halfRoll);
|
||
var cosRoll = Math.cos(halfRoll);
|
||
var sinPitch = Math.sin(halfPitch);
|
||
var cosPitch = Math.cos(halfPitch);
|
||
var sinYaw = Math.sin(halfYaw);
|
||
var cosYaw = Math.cos(halfYaw);
|
||
var oe = out.elements;
|
||
oe[0] = (cosYaw * sinPitch * cosRoll) + (sinYaw * cosPitch * sinRoll);
|
||
oe[1] = (sinYaw * cosPitch * cosRoll) - (cosYaw * sinPitch * sinRoll);
|
||
oe[2] = (cosYaw * cosPitch * sinRoll) - (sinYaw * sinPitch * cosRoll);
|
||
oe[3] = (cosYaw * cosPitch * cosRoll) + (sinYaw * sinPitch * sinRoll);
|
||
}
|
||
static multiply(left, right, out) {
|
||
var le = left.elements;
|
||
var re = right.elements;
|
||
var oe = out.elements;
|
||
var lx = le[0];
|
||
var ly = le[1];
|
||
var lz = le[2];
|
||
var lw = le[3];
|
||
var rx = re[0];
|
||
var ry = re[1];
|
||
var rz = re[2];
|
||
var rw = re[3];
|
||
var a = (ly * rz - lz * ry);
|
||
var b = (lz * rx - lx * rz);
|
||
var c = (lx * ry - ly * rx);
|
||
var d = (lx * rx + ly * ry + lz * rz);
|
||
oe[0] = (lx * rw + rx * lw) + a;
|
||
oe[1] = (ly * rw + ry * lw) + b;
|
||
oe[2] = (lz * rw + rz * lw) + c;
|
||
oe[3] = lw * rw - d;
|
||
}
|
||
static arcTanAngle(x, y) {
|
||
if (x == 0) {
|
||
if (y == 1)
|
||
return Math.PI / 2;
|
||
return -Math.PI / 2;
|
||
}
|
||
if (x > 0)
|
||
return Math.atan(y / x);
|
||
if (x < 0) {
|
||
if (y > 0)
|
||
return Math.atan(y / x) + Math.PI;
|
||
return Math.atan(y / x) - Math.PI;
|
||
}
|
||
return 0;
|
||
}
|
||
static angleTo(from, location, angle) {
|
||
ConchVector3.subtract(location, from, ConchQuaternion.TEMPVector30);
|
||
ConchVector3.normalize(ConchQuaternion.TEMPVector30, ConchQuaternion.TEMPVector30);
|
||
angle.elements[0] = Math.asin(ConchQuaternion.TEMPVector30.y);
|
||
angle.elements[1] = ConchQuaternion.arcTanAngle(-ConchQuaternion.TEMPVector30.z, -ConchQuaternion.TEMPVector30.x);
|
||
}
|
||
static createFromAxisAngle(axis, rad, out) {
|
||
var e = out.elements;
|
||
var f = axis.elements;
|
||
rad = rad * 0.5;
|
||
var s = Math.sin(rad);
|
||
e[0] = s * f[0];
|
||
e[1] = s * f[1];
|
||
e[2] = s * f[2];
|
||
e[3] = Math.cos(rad);
|
||
}
|
||
static createFromMatrix3x3(sou, out) {
|
||
var e = out.elements;
|
||
var f = sou.elements;
|
||
var fTrace = f[0] + f[4] + f[8];
|
||
var fRoot;
|
||
if (fTrace > 0.0) {
|
||
fRoot = Math.sqrt(fTrace + 1.0);
|
||
e[3] = 0.5 * fRoot;
|
||
fRoot = 0.5 / fRoot;
|
||
e[0] = (f[5] - f[7]) * fRoot;
|
||
e[1] = (f[6] - f[2]) * fRoot;
|
||
e[2] = (f[1] - f[3]) * fRoot;
|
||
}
|
||
else {
|
||
var i = 0;
|
||
if (f[4] > f[0])
|
||
i = 1;
|
||
if (f[8] > f[i * 3 + i])
|
||
i = 2;
|
||
var j = (i + 1) % 3;
|
||
var k = (i + 2) % 3;
|
||
fRoot = Math.sqrt(f[i * 3 + i] - f[j * 3 + j] - f[k * 3 + k] + 1.0);
|
||
e[i] = 0.5 * fRoot;
|
||
fRoot = 0.5 / fRoot;
|
||
e[3] = (f[j * 3 + k] - f[k * 3 + j]) * fRoot;
|
||
e[j] = (f[j * 3 + i] + f[i * 3 + j]) * fRoot;
|
||
e[k] = (f[k * 3 + i] + f[i * 3 + k]) * fRoot;
|
||
}
|
||
return;
|
||
}
|
||
static createFromMatrix4x4(mat, out) {
|
||
var me = mat.elements;
|
||
var oe = out.elements;
|
||
var sqrt;
|
||
var half;
|
||
var scale = me[0] + me[5] + me[10];
|
||
if (scale > 0.0) {
|
||
sqrt = Math.sqrt(scale + 1.0);
|
||
oe[3] = sqrt * 0.5;
|
||
sqrt = 0.5 / sqrt;
|
||
oe[0] = (me[6] - me[9]) * sqrt;
|
||
oe[1] = (me[8] - me[2]) * sqrt;
|
||
oe[2] = (me[1] - me[4]) * sqrt;
|
||
}
|
||
else if ((me[0] >= me[5]) && (me[0] >= me[10])) {
|
||
sqrt = Math.sqrt(1.0 + me[0] - me[5] - me[10]);
|
||
half = 0.5 / sqrt;
|
||
oe[0] = 0.5 * sqrt;
|
||
oe[1] = (me[1] + me[4]) * half;
|
||
oe[2] = (me[2] + me[8]) * half;
|
||
oe[3] = (me[6] - me[9]) * half;
|
||
}
|
||
else if (me[5] > me[10]) {
|
||
sqrt = Math.sqrt(1.0 + me[5] - me[0] - me[10]);
|
||
half = 0.5 / sqrt;
|
||
oe[0] = (me[4] + me[1]) * half;
|
||
oe[1] = 0.5 * sqrt;
|
||
oe[2] = (me[9] + me[6]) * half;
|
||
oe[3] = (me[8] - me[2]) * half;
|
||
}
|
||
else {
|
||
sqrt = Math.sqrt(1.0 + me[10] - me[0] - me[5]);
|
||
half = 0.5 / sqrt;
|
||
oe[0] = (me[8] + me[2]) * half;
|
||
oe[1] = (me[9] + me[6]) * half;
|
||
oe[2] = 0.5 * sqrt;
|
||
oe[3] = (me[1] - me[4]) * half;
|
||
}
|
||
}
|
||
static slerp(left, right, t, out) {
|
||
var a = left.elements;
|
||
var b = right.elements;
|
||
var oe = out.elements;
|
||
var ax = a[0], ay = a[1], az = a[2], aw = a[3], bx = b[0], by = b[1], bz = b[2], bw = b[3];
|
||
var omega, cosom, sinom, scale0, scale1;
|
||
cosom = ax * bx + ay * by + az * bz + aw * bw;
|
||
if (cosom < 0.0) {
|
||
cosom = -cosom;
|
||
bx = -bx;
|
||
by = -by;
|
||
bz = -bz;
|
||
bw = -bw;
|
||
}
|
||
if ((1.0 - cosom) > 0.000001) {
|
||
omega = Math.acos(cosom);
|
||
sinom = Math.sin(omega);
|
||
scale0 = Math.sin((1.0 - t) * omega) / sinom;
|
||
scale1 = Math.sin(t * omega) / sinom;
|
||
}
|
||
else {
|
||
scale0 = 1.0 - t;
|
||
scale1 = t;
|
||
}
|
||
oe[0] = scale0 * ax + scale1 * bx;
|
||
oe[1] = scale0 * ay + scale1 * by;
|
||
oe[2] = scale0 * az + scale1 * bz;
|
||
oe[3] = scale0 * aw + scale1 * bw;
|
||
return oe;
|
||
}
|
||
static lerp(left, right, amount, out) {
|
||
ConchQuaternion._lerpArray(left.elements, right.elements, amount, out.elements);
|
||
}
|
||
static add(left, right, out) {
|
||
var e = out.elements;
|
||
var f = left.elements;
|
||
var g = right.elements;
|
||
e[0] = f[0] + g[0];
|
||
e[1] = f[1] + g[1];
|
||
e[2] = f[2] + g[2];
|
||
e[3] = f[3] + g[3];
|
||
}
|
||
static dot(left, right) {
|
||
return ConchQuaternion._dotArray(left.elements, right.elements);
|
||
}
|
||
get x() {
|
||
return this.elements[0];
|
||
}
|
||
set x(value) {
|
||
this.elements[0] = value;
|
||
}
|
||
get y() {
|
||
return this.elements[1];
|
||
}
|
||
set y(value) {
|
||
this.elements[1] = value;
|
||
}
|
||
get z() {
|
||
return this.elements[2];
|
||
}
|
||
set z(value) {
|
||
this.elements[2] = value;
|
||
}
|
||
get w() {
|
||
return this.elements[3];
|
||
}
|
||
set w(value) {
|
||
this.elements[3] = value;
|
||
}
|
||
scaling(scaling, out) {
|
||
var e = out.elements;
|
||
var f = this.elements;
|
||
e[0] = f[0] * scaling;
|
||
e[1] = f[1] * scaling;
|
||
e[2] = f[2] * scaling;
|
||
e[3] = f[3] * scaling;
|
||
}
|
||
normalize(out) {
|
||
ConchQuaternion._normalizeArray(this.elements, out.elements);
|
||
}
|
||
length() {
|
||
var f = this.elements;
|
||
var x = f[0], y = f[1], z = f[2], w = f[3];
|
||
return Math.sqrt(x * x + y * y + z * z + w * w);
|
||
}
|
||
rotateX(rad, out) {
|
||
var e = out.elements;
|
||
var f = this.elements;
|
||
rad *= 0.5;
|
||
var ax = f[0], ay = f[1], az = f[2], aw = f[3];
|
||
var bx = Math.sin(rad), bw = Math.cos(rad);
|
||
e[0] = ax * bw + aw * bx;
|
||
e[1] = ay * bw + az * bx;
|
||
e[2] = az * bw - ay * bx;
|
||
e[3] = aw * bw - ax * bx;
|
||
}
|
||
rotateY(rad, out) {
|
||
var e = out.elements;
|
||
var f = this.elements;
|
||
rad *= 0.5;
|
||
var ax = f[0], ay = f[1], az = f[2], aw = f[3], by = Math.sin(rad), bw = Math.cos(rad);
|
||
e[0] = ax * bw - az * by;
|
||
e[1] = ay * bw + aw * by;
|
||
e[2] = az * bw + ax * by;
|
||
e[3] = aw * bw - ay * by;
|
||
}
|
||
rotateZ(rad, out) {
|
||
var e = out.elements;
|
||
var f = this.elements;
|
||
rad *= 0.5;
|
||
var ax = f[0], ay = f[1], az = f[2], aw = f[3], bz = Math.sin(rad), bw = Math.cos(rad);
|
||
e[0] = ax * bw + ay * bz;
|
||
e[1] = ay * bw - ax * bz;
|
||
e[2] = az * bw + aw * bz;
|
||
e[3] = aw * bw - az * bz;
|
||
}
|
||
getYawPitchRoll(out) {
|
||
ConchVector3.transformQuat(ConchVector3.ForwardRH, this, ConchQuaternion.TEMPVector31);
|
||
ConchVector3.transformQuat(ConchVector3.Up, this, ConchQuaternion.TEMPVector32);
|
||
var upe = ConchQuaternion.TEMPVector32.elements;
|
||
ConchQuaternion.angleTo(ConchVector3.ZERO, ConchQuaternion.TEMPVector31, ConchQuaternion.TEMPVector33);
|
||
var anglee = ConchQuaternion.TEMPVector33.elements;
|
||
if (anglee[0] == Math.PI / 2) {
|
||
anglee[1] = ConchQuaternion.arcTanAngle(upe[2], upe[0]);
|
||
anglee[2] = 0;
|
||
}
|
||
else if (anglee[0] == -Math.PI / 2) {
|
||
anglee[1] = ConchQuaternion.arcTanAngle(-upe[2], -upe[0]);
|
||
anglee[2] = 0;
|
||
}
|
||
else {
|
||
Matrix4x4.createRotationY(-anglee[1], ConchQuaternion.TEMPMatrix0);
|
||
Matrix4x4.createRotationX(-anglee[0], ConchQuaternion.TEMPMatrix1);
|
||
ConchVector3.transformCoordinate(ConchQuaternion.TEMPVector32, ConchQuaternion.TEMPMatrix0, ConchQuaternion.TEMPVector32);
|
||
ConchVector3.transformCoordinate(ConchQuaternion.TEMPVector32, ConchQuaternion.TEMPMatrix1, ConchQuaternion.TEMPVector32);
|
||
anglee[2] = ConchQuaternion.arcTanAngle(upe[1], -upe[0]);
|
||
}
|
||
if (anglee[1] <= -Math.PI)
|
||
anglee[1] = Math.PI;
|
||
if (anglee[2] <= -Math.PI)
|
||
anglee[2] = Math.PI;
|
||
if (anglee[1] >= Math.PI && anglee[2] >= Math.PI) {
|
||
anglee[1] = 0;
|
||
anglee[2] = 0;
|
||
anglee[0] = Math.PI - anglee[0];
|
||
}
|
||
var oe = out.elements;
|
||
oe[0] = anglee[1];
|
||
oe[1] = anglee[0];
|
||
oe[2] = anglee[2];
|
||
}
|
||
invert(out) {
|
||
var e = out.elements;
|
||
var f = this.elements;
|
||
var a0 = f[0], a1 = f[1], a2 = f[2], a3 = f[3];
|
||
var dot = a0 * a0 + a1 * a1 + a2 * a2 + a3 * a3;
|
||
var invDot = dot ? 1.0 / dot : 0;
|
||
e[0] = -a0 * invDot;
|
||
e[1] = -a1 * invDot;
|
||
e[2] = -a2 * invDot;
|
||
e[3] = a3 * invDot;
|
||
}
|
||
identity() {
|
||
var e = this.elements;
|
||
e[0] = 0;
|
||
e[1] = 0;
|
||
e[2] = 0;
|
||
e[3] = 1;
|
||
}
|
||
fromArray(array, offset = 0) {
|
||
this.elements[0] = array[offset + 0];
|
||
this.elements[1] = array[offset + 1];
|
||
this.elements[2] = array[offset + 2];
|
||
this.elements[3] = array[offset + 3];
|
||
}
|
||
cloneTo(destObject) {
|
||
var i, s, d;
|
||
s = this.elements;
|
||
d = destObject.elements;
|
||
if (s === d) {
|
||
return;
|
||
}
|
||
for (i = 0; i < 4; ++i) {
|
||
d[i] = s[i];
|
||
}
|
||
}
|
||
clone() {
|
||
var dest = new ConchQuaternion();
|
||
this.cloneTo(dest);
|
||
return dest;
|
||
}
|
||
equals(b) {
|
||
var ae = this.elements;
|
||
var be = b.elements;
|
||
return MathUtils3D.nearEqual(ae[0], be[0]) && MathUtils3D.nearEqual(ae[1], be[1]) && MathUtils3D.nearEqual(ae[2], be[2]) && MathUtils3D.nearEqual(ae[3], be[3]);
|
||
}
|
||
static rotationLookAt(forward, up, out) {
|
||
ConchQuaternion.lookAt(ConchVector3.ZERO, forward, up, out);
|
||
}
|
||
static lookAt(eye, target, up, out) {
|
||
Matrix3x3.lookAt(eye, target, up, ConchQuaternion._tempMatrix3x3);
|
||
ConchQuaternion.rotationMatrix(ConchQuaternion._tempMatrix3x3, out);
|
||
}
|
||
lengthSquared() {
|
||
var x = this.elements[0];
|
||
var y = this.elements[1];
|
||
var z = this.elements[2];
|
||
var w = this.elements[3];
|
||
return (x * x) + (y * y) + (z * z) + (w * w);
|
||
}
|
||
static invert(value, out) {
|
||
var vE = value.elements;
|
||
var oE = out.elements;
|
||
var lengthSq = value.lengthSquared();
|
||
if (!MathUtils3D.isZero(lengthSq)) {
|
||
lengthSq = 1.0 / lengthSq;
|
||
oE[0] = -vE[0] * lengthSq;
|
||
oE[1] = -vE[1] * lengthSq;
|
||
oE[2] = -vE[2] * lengthSq;
|
||
oE[3] = vE[3] * lengthSq;
|
||
}
|
||
}
|
||
static rotationMatrix(matrix3x3, out) {
|
||
var me = matrix3x3.elements;
|
||
var m11 = me[0];
|
||
var m12 = me[1];
|
||
var m13 = me[2];
|
||
var m21 = me[3];
|
||
var m22 = me[4];
|
||
var m23 = me[5];
|
||
var m31 = me[6];
|
||
var m32 = me[7];
|
||
var m33 = me[8];
|
||
var oe = out.elements;
|
||
var sqrt, half;
|
||
var scale = m11 + m22 + m33;
|
||
if (scale > 0) {
|
||
sqrt = Math.sqrt(scale + 1);
|
||
oe[3] = sqrt * 0.5;
|
||
sqrt = 0.5 / sqrt;
|
||
oe[0] = (m23 - m32) * sqrt;
|
||
oe[1] = (m31 - m13) * sqrt;
|
||
oe[2] = (m12 - m21) * sqrt;
|
||
}
|
||
else if ((m11 >= m22) && (m11 >= m33)) {
|
||
sqrt = Math.sqrt(1 + m11 - m22 - m33);
|
||
half = 0.5 / sqrt;
|
||
oe[0] = 0.5 * sqrt;
|
||
oe[1] = (m12 + m21) * half;
|
||
oe[2] = (m13 + m31) * half;
|
||
oe[3] = (m23 - m32) * half;
|
||
}
|
||
else if (m22 > m33) {
|
||
sqrt = Math.sqrt(1 + m22 - m11 - m33);
|
||
half = 0.5 / sqrt;
|
||
oe[0] = (m21 + m12) * half;
|
||
oe[1] = 0.5 * sqrt;
|
||
oe[2] = (m32 + m23) * half;
|
||
oe[3] = (m31 - m13) * half;
|
||
}
|
||
else {
|
||
sqrt = Math.sqrt(1 + m33 - m11 - m22);
|
||
half = 0.5 / sqrt;
|
||
oe[0] = (m31 + m13) * half;
|
||
oe[1] = (m32 + m23) * half;
|
||
oe[2] = 0.5 * sqrt;
|
||
oe[3] = (m12 - m21) * half;
|
||
}
|
||
}
|
||
}
|
||
ConchQuaternion.TEMPVector30 = new ConchVector3();
|
||
ConchQuaternion.TEMPVector31 = new ConchVector3();
|
||
ConchQuaternion.TEMPVector32 = new ConchVector3();
|
||
ConchQuaternion.TEMPVector33 = new ConchVector3();
|
||
ConchQuaternion.TEMPMatrix0 = new Matrix4x4();
|
||
ConchQuaternion.TEMPMatrix1 = new Matrix4x4();
|
||
ConchQuaternion._tempMatrix3x3 = new Matrix3x3();
|
||
ConchQuaternion.DEFAULT = new ConchQuaternion();
|
||
ConchQuaternion.NAN = new ConchQuaternion(NaN, NaN, NaN, NaN);
|
||
|
||
class RandX {
|
||
constructor(seed) {
|
||
if (!(seed instanceof Array) || seed.length !== 4)
|
||
throw new Error('Rand:Seed must be an array with 4 numbers');
|
||
this._state0U = seed[0] | 0;
|
||
this._state0L = seed[1] | 0;
|
||
this._state1U = seed[2] | 0;
|
||
this._state1L = seed[3] | 0;
|
||
}
|
||
randomint() {
|
||
var s1U = this._state0U, s1L = this._state0L;
|
||
var s0U = this._state1U, s0L = this._state1L;
|
||
var sumL = (s0L >>> 0) + (s1L >>> 0);
|
||
var resU = (s0U + s1U + (sumL / 2 >>> 31)) >>> 0;
|
||
var resL = sumL >>> 0;
|
||
this._state0U = s0U;
|
||
this._state0L = s0L;
|
||
var t1U = 0, t1L = 0;
|
||
var t2U = 0, t2L = 0;
|
||
var a1 = 23;
|
||
var m1 = 0xFFFFFFFF << (32 - a1);
|
||
t1U = (s1U << a1) | ((s1L & m1) >>> (32 - a1));
|
||
t1L = s1L << a1;
|
||
s1U = s1U ^ t1U;
|
||
s1L = s1L ^ t1L;
|
||
t1U = s1U ^ s0U;
|
||
t1L = s1L ^ s0L;
|
||
var a2 = 18;
|
||
var m2 = 0xFFFFFFFF >>> (32 - a2);
|
||
t2U = s1U >>> a2;
|
||
t2L = (s1L >>> a2) | ((s1U & m2) << (32 - a2));
|
||
t1U = t1U ^ t2U;
|
||
t1L = t1L ^ t2L;
|
||
var a3 = 5;
|
||
var m3 = 0xFFFFFFFF >>> (32 - a3);
|
||
t2U = s0U >>> a3;
|
||
t2L = (s0L >>> a3) | ((s0U & m3) << (32 - a3));
|
||
t1U = t1U ^ t2U;
|
||
t1L = t1L ^ t2L;
|
||
this._state1U = t1U;
|
||
this._state1L = t1L;
|
||
return [resU, resL];
|
||
}
|
||
random() {
|
||
var t2 = this.randomint();
|
||
var t2U = t2[0];
|
||
var t2L = t2[1];
|
||
var eU = 0x3FF << (52 - 32);
|
||
var eL = 0;
|
||
var a1 = 12;
|
||
var m1 = 0xFFFFFFFF >>> (32 - a1);
|
||
var sU = t2U >>> a1;
|
||
var sL = (t2L >>> a1) | ((t2U & m1) << (32 - a1));
|
||
var xU = eU | sU;
|
||
var xL = eL | sL;
|
||
RandX._CONVERTION_BUFFER.setUint32(0, xU, false);
|
||
RandX._CONVERTION_BUFFER.setUint32(4, xL, false);
|
||
var d = RandX._CONVERTION_BUFFER.getFloat64(0, false);
|
||
return d - 1;
|
||
}
|
||
}
|
||
RandX._CONVERTION_BUFFER = new DataView(new ArrayBuffer(8));
|
||
RandX.defaultRand = new RandX([0, Date.now() / 65536, 0, Date.now() % 65536]);
|
||
|
||
class TextMesh {
|
||
constructor() {
|
||
}
|
||
get text() {
|
||
return this._text;
|
||
}
|
||
set text(value) {
|
||
this._text = value;
|
||
}
|
||
get fontSize() {
|
||
return this._fontSize;
|
||
}
|
||
set fontSize(value) {
|
||
this._fontSize = value;
|
||
}
|
||
get color() {
|
||
return this._color;
|
||
}
|
||
set color(value) {
|
||
this._color = value;
|
||
}
|
||
}
|
||
|
||
class Size {
|
||
constructor(width, height) {
|
||
this._width = 0;
|
||
this._height = 0;
|
||
this._width = width;
|
||
this._height = height;
|
||
}
|
||
static get fullScreen() {
|
||
return new Size(-1, -1);
|
||
}
|
||
get width() {
|
||
if (this._width === -1)
|
||
return RenderContext3D.clientWidth;
|
||
return this._width;
|
||
}
|
||
get height() {
|
||
if (this._height === -1)
|
||
return RenderContext3D.clientHeight;
|
||
return this._height;
|
||
}
|
||
}
|
||
|
||
exports.AlternateLightQueue = AlternateLightQueue;
|
||
exports.AnimationClip = AnimationClip;
|
||
exports.AnimationClipParser03 = AnimationClipParser03;
|
||
exports.AnimationClipParser04 = AnimationClipParser04;
|
||
exports.AnimationEvent = AnimationEvent;
|
||
exports.AnimationNode = AnimationNode;
|
||
exports.AnimationTransform3D = AnimationTransform3D;
|
||
exports.Animator = Animator;
|
||
exports.AnimatorControllerLayer = AnimatorControllerLayer;
|
||
exports.AnimatorPlayState = AnimatorPlayState;
|
||
exports.AnimatorState = AnimatorState;
|
||
exports.AnimatorStateScript = AnimatorStateScript;
|
||
exports.Avatar = Avatar;
|
||
exports.AvatarMask = AvatarMask;
|
||
exports.BaseCamera = BaseCamera;
|
||
exports.BaseMaterial = BaseMaterial;
|
||
exports.BaseRender = BaseRender;
|
||
exports.BaseShape = BaseShape;
|
||
exports.BatchMark = BatchMark;
|
||
exports.BlinnPhongMaterial = BlinnPhongMaterial;
|
||
exports.BlitScreenQuadCMD = BlitScreenQuadCMD;
|
||
exports.BloomEffect = BloomEffect;
|
||
exports.BoundBox = BoundBox;
|
||
exports.BoundFrustum = BoundFrustum;
|
||
exports.BoundSphere = BoundSphere;
|
||
exports.Bounds = Bounds;
|
||
exports.BoundsOctree = BoundsOctree;
|
||
exports.BoundsOctreeNode = BoundsOctreeNode;
|
||
exports.BoxShape = BoxShape;
|
||
exports.BufferState = BufferState;
|
||
exports.Burst = Burst;
|
||
exports.Camera = Camera;
|
||
exports.CameraCullInfo = CameraCullInfo;
|
||
exports.CastShadowList = CastShadowList;
|
||
exports.CircleShape = CircleShape;
|
||
exports.ClearRenderTextureCMD = ClearRenderTextureCMD;
|
||
exports.Cluster = Cluster;
|
||
exports.CollisionUtils = CollisionUtils;
|
||
exports.Color = Color;
|
||
exports.ColorOverLifetime = ColorOverLifetime;
|
||
exports.Command = Command;
|
||
exports.CommandBuffer = CommandBuffer;
|
||
exports.ConchQuaternion = ConchQuaternion;
|
||
exports.ConchVector3 = ConchVector3;
|
||
exports.ConchVector4 = ConchVector4;
|
||
exports.ConeShape = ConeShape;
|
||
exports.Config3D = Config3D;
|
||
exports.ContainmentType = ContainmentType;
|
||
exports.DefineDatas = DefineDatas;
|
||
exports.DepthPass = DepthPass;
|
||
exports.DirectionLight = DirectionLight;
|
||
exports.DrawMeshCMD = DrawMeshCMD;
|
||
exports.DrawMeshInstancedCMD = DrawMeshInstancedCMD;
|
||
exports.DrawRenderCMD = DrawRenderCMD;
|
||
exports.DynamicBatchManager = DynamicBatchManager;
|
||
exports.EffectMaterial = EffectMaterial;
|
||
exports.Emission = Emission;
|
||
exports.ExtendTerrainMaterial = ExtendTerrainMaterial;
|
||
exports.FloatKeyframe = FloatKeyframe;
|
||
exports.FrameOverTime = FrameOverTime;
|
||
exports.FrustumCulling = FrustumCulling;
|
||
exports.GeometryElement = GeometryElement;
|
||
exports.Gradient = Gradient;
|
||
exports.GradientAngularVelocity = GradientAngularVelocity;
|
||
exports.GradientColor = GradientColor;
|
||
exports.GradientDataInt = GradientDataInt;
|
||
exports.GradientDataNumber = GradientDataNumber;
|
||
exports.GradientDataVector2 = GradientDataVector2;
|
||
exports.GradientMode = GradientMode;
|
||
exports.GradientSize = GradientSize;
|
||
exports.GradientVelocity = GradientVelocity;
|
||
exports.HeightMap = HeightMap;
|
||
exports.HemisphereShape = HemisphereShape;
|
||
exports.ILaya3D = ILaya3D;
|
||
exports.IndexBuffer3D = IndexBuffer3D;
|
||
exports.Input3D = Input3D;
|
||
exports.Keyframe = Keyframe;
|
||
exports.KeyframeNode = KeyframeNode;
|
||
exports.KeyframeNodeList = KeyframeNodeList;
|
||
exports.KeyframeNodeOwner = KeyframeNodeOwner;
|
||
exports.Laya3D = Laya3D;
|
||
exports.LightQueue = LightQueue;
|
||
exports.LightSprite = LightSprite;
|
||
exports.Lightmap = Lightmap;
|
||
exports.LoadModelV04 = LoadModelV04;
|
||
exports.LoadModelV05 = LoadModelV05;
|
||
exports.Material = Material;
|
||
exports.MaterialInstanceProperty = MaterialInstanceProperty;
|
||
exports.MaterialInstancePropertyBlock = MaterialInstancePropertyBlock;
|
||
exports.MathUtils3D = MathUtils3D;
|
||
exports.Matrix3x3 = Matrix3x3;
|
||
exports.Matrix4x4 = Matrix4x4;
|
||
exports.Mesh = Mesh;
|
||
exports.MeshFilter = MeshFilter;
|
||
exports.MeshReader = MeshReader;
|
||
exports.MeshRenderDynamicBatchManager = MeshRenderDynamicBatchManager;
|
||
exports.MeshRenderStaticBatchManager = MeshRenderStaticBatchManager;
|
||
exports.MeshRenderer = MeshRenderer;
|
||
exports.MeshSprite3D = MeshSprite3D;
|
||
exports.MeshSprite3DShaderDeclaration = MeshSprite3DShaderDeclaration;
|
||
exports.MeshTerrainSprite3D = MeshTerrainSprite3D;
|
||
exports.MouseTouch = MouseTouch;
|
||
exports.OctreeMotionList = OctreeMotionList;
|
||
exports.PBRMaterial = PBRMaterial;
|
||
exports.PBRSpecularMaterial = PBRSpecularMaterial;
|
||
exports.PBRStandardMaterial = PBRStandardMaterial;
|
||
exports.Physics3D = Physics3D;
|
||
exports.Physics3DUtils = Physics3DUtils;
|
||
exports.Picker = Picker;
|
||
exports.PixelLineData = PixelLineData;
|
||
exports.PixelLineFilter = PixelLineFilter;
|
||
exports.PixelLineMaterial = PixelLineMaterial;
|
||
exports.PixelLineRenderer = PixelLineRenderer;
|
||
exports.PixelLineSprite3D = PixelLineSprite3D;
|
||
exports.PixelLineVertex = PixelLineVertex;
|
||
exports.Plane = Plane;
|
||
exports.PointLight = PointLight;
|
||
exports.PostProcess = PostProcess;
|
||
exports.PostProcessEffect = PostProcessEffect;
|
||
exports.PostProcessRenderContext = PostProcessRenderContext;
|
||
exports.PrimitiveMesh = PrimitiveMesh;
|
||
exports.Quaternion = Quaternion;
|
||
exports.QuaternionKeyframe = QuaternionKeyframe;
|
||
exports.Rand = Rand;
|
||
exports.RandX = RandX;
|
||
exports.Ray = Ray;
|
||
exports.ReflectionProbe = ReflectionProbe;
|
||
exports.ReflectionProbeList = ReflectionProbeList;
|
||
exports.ReflectionProbeManager = ReflectionProbeManager;
|
||
exports.RenderContext3D = RenderContext3D;
|
||
exports.RenderElement = RenderElement;
|
||
exports.RenderQueue = RenderQueue;
|
||
exports.RenderState = RenderState;
|
||
exports.RenderTexture = RenderTexture;
|
||
exports.RenderableSprite3D = RenderableSprite3D;
|
||
exports.RotationOverLifetime = RotationOverLifetime;
|
||
exports.Scene3D = Scene3D;
|
||
exports.Scene3DShaderDeclaration = Scene3DShaderDeclaration;
|
||
exports.Scene3DUtils = Scene3DUtils;
|
||
exports.ScreenQuad = ScreenQuad;
|
||
exports.ScreenTriangle = ScreenTriangle;
|
||
exports.Script3D = Script3D;
|
||
exports.SetGlobalShaderDataCMD = SetGlobalShaderDataCMD;
|
||
exports.SetRenderTargetCMD = SetRenderTargetCMD;
|
||
exports.SetShaderDataCMD = SetShaderDataCMD;
|
||
exports.Shader3D = Shader3D;
|
||
exports.ShaderData = ShaderData;
|
||
exports.ShaderDefine = ShaderDefine;
|
||
exports.ShaderInit3D = ShaderInit3D;
|
||
exports.ShaderInstance = ShaderInstance;
|
||
exports.ShaderPass = ShaderPass;
|
||
exports.ShaderVariable = ShaderVariable;
|
||
exports.ShaderVariant = ShaderVariant;
|
||
exports.ShaderVariantCollection = ShaderVariantCollection;
|
||
exports.ShadowCasterPass = ShadowCasterPass;
|
||
exports.ShadowCullInfo = ShadowCullInfo;
|
||
exports.ShadowSliceData = ShadowSliceData;
|
||
exports.ShadowSpotData = ShadowSpotData;
|
||
exports.ShadowUtils = ShadowUtils;
|
||
exports.ShapeUtils = ShapeUtils;
|
||
exports.ShuriKenParticle3D = ShuriKenParticle3D;
|
||
exports.ShuriKenParticle3DShaderDeclaration = ShuriKenParticle3DShaderDeclaration;
|
||
exports.ShurikenParticleData = ShurikenParticleData;
|
||
exports.ShurikenParticleMaterial = ShurikenParticleMaterial;
|
||
exports.ShurikenParticleRenderer = ShurikenParticleRenderer;
|
||
exports.ShurikenParticleSystem = ShurikenParticleSystem;
|
||
exports.SimpleSingletonList = SimpleSingletonList;
|
||
exports.SimpleSkinnedMeshRenderer = SimpleSkinnedMeshRenderer;
|
||
exports.SimpleSkinnedMeshSprite3D = SimpleSkinnedMeshSprite3D;
|
||
exports.SingletonList = SingletonList;
|
||
exports.Size = Size;
|
||
exports.SizeOverLifetime = SizeOverLifetime;
|
||
exports.SkinnedMeshRenderer = SkinnedMeshRenderer;
|
||
exports.SkinnedMeshSprite3D = SkinnedMeshSprite3D;
|
||
exports.SkinnedMeshSprite3DShaderDeclaration = SkinnedMeshSprite3DShaderDeclaration;
|
||
exports.SkyBox = SkyBox;
|
||
exports.SkyBoxMaterial = SkyBoxMaterial;
|
||
exports.SkyDome = SkyDome;
|
||
exports.SkyMesh = SkyMesh;
|
||
exports.SkyPanoramicMaterial = SkyPanoramicMaterial;
|
||
exports.SkyProceduralMaterial = SkyProceduralMaterial;
|
||
exports.SkyRenderer = SkyRenderer;
|
||
exports.SphereShape = SphereShape;
|
||
exports.SphericalHarmonicsL2 = SphericalHarmonicsL2;
|
||
exports.SpotLight = SpotLight;
|
||
exports.Sprite3D = Sprite3D;
|
||
exports.StartFrame = StartFrame;
|
||
exports.StaticBatchManager = StaticBatchManager;
|
||
exports.SubMesh = SubMesh;
|
||
exports.SubMeshDynamicBatch = SubMeshDynamicBatch;
|
||
exports.SubMeshInstanceBatch = SubMeshInstanceBatch;
|
||
exports.SubMeshRenderElement = SubMeshRenderElement;
|
||
exports.SubMeshStaticBatch = SubMeshStaticBatch;
|
||
exports.SubShader = SubShader;
|
||
exports.TextMesh = TextMesh;
|
||
exports.TextureCube = TextureCube;
|
||
exports.TextureGenerator = TextureGenerator;
|
||
exports.TextureMode = TextureMode;
|
||
exports.TextureSheetAnimation = TextureSheetAnimation;
|
||
exports.Touch = Touch;
|
||
exports.TrailFilter = TrailFilter;
|
||
exports.TrailGeometry = TrailGeometry;
|
||
exports.TrailMaterial = TrailMaterial;
|
||
exports.TrailRenderer = TrailRenderer;
|
||
exports.TrailSprite3D = TrailSprite3D;
|
||
exports.Transform3D = Transform3D;
|
||
exports.UnlitMaterial = UnlitMaterial;
|
||
exports.Utils3D = Utils3D;
|
||
exports.Vector2 = Vector2;
|
||
exports.Vector3 = Vector3;
|
||
exports.Vector3Keyframe = Vector3Keyframe;
|
||
exports.Vector4 = Vector4;
|
||
exports.VelocityOverLifetime = VelocityOverLifetime;
|
||
exports.VertexBuffer3D = VertexBuffer3D;
|
||
exports.VertexDeclaration = VertexDeclaration;
|
||
exports.VertexElement = VertexElement;
|
||
exports.VertexElementFormat = VertexElementFormat;
|
||
exports.VertexMesh = VertexMesh;
|
||
exports.VertexPositionTerrain = VertexPositionTerrain;
|
||
exports.VertexPositionTexture0 = VertexPositionTexture0;
|
||
exports.VertexShuriKenParticle = VertexShuriKenParticle;
|
||
exports.VertexShurikenParticleBillboard = VertexShurikenParticleBillboard;
|
||
exports.VertexShurikenParticleMesh = VertexShurikenParticleMesh;
|
||
exports.VertexTrail = VertexTrail;
|
||
exports.Viewport = Viewport;
|
||
exports.WaterPrimaryMaterial = WaterPrimaryMaterial;
|
||
exports.skinnedMatrixCache = skinnedMatrixCache;
|
||
|
||
}(window.Laya = window.Laya || {}, Laya));
|