@openhps/core
Version:
Open Hybrid Positioning System - Core component
254 lines (245 loc) • 10.3 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.textureCubeUV = exports.getDirection = exports.blur = void 0;
var _TSLBase = require("../tsl/TSLBase.js");
var _MathNode = require("../math/MathNode.js");
var _OperatorNode = require("../math/OperatorNode.js");
var _ConditionalNode = require("../math/ConditionalNode.js");
var _LoopNode = require("../utils/LoopNode.js");
// These defines must match with PMREMGenerator
const cubeUV_r0 = /*@__PURE__*/(0, _TSLBase.float)(1.0);
const cubeUV_m0 = /*@__PURE__*/(0, _TSLBase.float)(-2.0);
const cubeUV_r1 = /*@__PURE__*/(0, _TSLBase.float)(0.8);
const cubeUV_m1 = /*@__PURE__*/(0, _TSLBase.float)(-1.0);
const cubeUV_r4 = /*@__PURE__*/(0, _TSLBase.float)(0.4);
const cubeUV_m4 = /*@__PURE__*/(0, _TSLBase.float)(2.0);
const cubeUV_r5 = /*@__PURE__*/(0, _TSLBase.float)(0.305);
const cubeUV_m5 = /*@__PURE__*/(0, _TSLBase.float)(3.0);
const cubeUV_r6 = /*@__PURE__*/(0, _TSLBase.float)(0.21);
const cubeUV_m6 = /*@__PURE__*/(0, _TSLBase.float)(4.0);
const cubeUV_minMipLevel = /*@__PURE__*/(0, _TSLBase.float)(4.0);
const cubeUV_minTileSize = /*@__PURE__*/(0, _TSLBase.float)(16.0);
// These shader functions convert between the UV coordinates of a single face of
// a cubemap, the 0-5 integer index of a cube face, and the direction vector for
// sampling a textureCube (not generally normalized ).
const getFace = /*@__PURE__*/(0, _TSLBase.Fn)(([direction]) => {
const absDirection = (0, _TSLBase.vec3)((0, _MathNode.abs)(direction)).toVar();
const face = (0, _TSLBase.float)(-1.0).toVar();
(0, _TSLBase.If)(absDirection.x.greaterThan(absDirection.z), () => {
(0, _TSLBase.If)(absDirection.x.greaterThan(absDirection.y), () => {
face.assign((0, _ConditionalNode.select)(direction.x.greaterThan(0.0), 0.0, 3.0));
}).Else(() => {
face.assign((0, _ConditionalNode.select)(direction.y.greaterThan(0.0), 1.0, 4.0));
});
}).Else(() => {
(0, _TSLBase.If)(absDirection.z.greaterThan(absDirection.y), () => {
face.assign((0, _ConditionalNode.select)(direction.z.greaterThan(0.0), 2.0, 5.0));
}).Else(() => {
face.assign((0, _ConditionalNode.select)(direction.y.greaterThan(0.0), 1.0, 4.0));
});
});
return face;
}).setLayout({
name: 'getFace',
type: 'float',
inputs: [{
name: 'direction',
type: 'vec3'
}]
});
// RH coordinate system; PMREM face-indexing convention
const getUV = /*@__PURE__*/(0, _TSLBase.Fn)(([direction, face]) => {
const uv = (0, _TSLBase.vec2)().toVar();
(0, _TSLBase.If)(face.equal(0.0), () => {
uv.assign((0, _TSLBase.vec2)(direction.z, direction.y).div((0, _MathNode.abs)(direction.x))); // pos x
}).ElseIf(face.equal(1.0), () => {
uv.assign((0, _TSLBase.vec2)(direction.x.negate(), direction.z.negate()).div((0, _MathNode.abs)(direction.y))); // pos y
}).ElseIf(face.equal(2.0), () => {
uv.assign((0, _TSLBase.vec2)(direction.x.negate(), direction.y).div((0, _MathNode.abs)(direction.z))); // pos z
}).ElseIf(face.equal(3.0), () => {
uv.assign((0, _TSLBase.vec2)(direction.z.negate(), direction.y).div((0, _MathNode.abs)(direction.x))); // neg x
}).ElseIf(face.equal(4.0), () => {
uv.assign((0, _TSLBase.vec2)(direction.x.negate(), direction.z).div((0, _MathNode.abs)(direction.y))); // neg y
}).Else(() => {
uv.assign((0, _TSLBase.vec2)(direction.x, direction.y).div((0, _MathNode.abs)(direction.z))); // neg z
});
return (0, _OperatorNode.mul)(0.5, uv.add(1.0));
}).setLayout({
name: 'getUV',
type: 'vec2',
inputs: [{
name: 'direction',
type: 'vec3'
}, {
name: 'face',
type: 'float'
}]
});
const roughnessToMip = /*@__PURE__*/(0, _TSLBase.Fn)(([roughness]) => {
const mip = (0, _TSLBase.float)(0.0).toVar();
(0, _TSLBase.If)(roughness.greaterThanEqual(cubeUV_r1), () => {
mip.assign(cubeUV_r0.sub(roughness).mul(cubeUV_m1.sub(cubeUV_m0)).div(cubeUV_r0.sub(cubeUV_r1)).add(cubeUV_m0));
}).ElseIf(roughness.greaterThanEqual(cubeUV_r4), () => {
mip.assign(cubeUV_r1.sub(roughness).mul(cubeUV_m4.sub(cubeUV_m1)).div(cubeUV_r1.sub(cubeUV_r4)).add(cubeUV_m1));
}).ElseIf(roughness.greaterThanEqual(cubeUV_r5), () => {
mip.assign(cubeUV_r4.sub(roughness).mul(cubeUV_m5.sub(cubeUV_m4)).div(cubeUV_r4.sub(cubeUV_r5)).add(cubeUV_m4));
}).ElseIf(roughness.greaterThanEqual(cubeUV_r6), () => {
mip.assign(cubeUV_r5.sub(roughness).mul(cubeUV_m6.sub(cubeUV_m5)).div(cubeUV_r5.sub(cubeUV_r6)).add(cubeUV_m5));
}).Else(() => {
mip.assign((0, _TSLBase.float)(-2.0).mul((0, _MathNode.log2)((0, _OperatorNode.mul)(1.16, roughness)))); // 1.16 = 1.79^0.25
});
return mip;
}).setLayout({
name: 'roughnessToMip',
type: 'float',
inputs: [{
name: 'roughness',
type: 'float'
}]
});
// RH coordinate system; PMREM face-indexing convention
const getDirection = exports.getDirection = /*@__PURE__*/(0, _TSLBase.Fn)(([uv_immutable, face]) => {
const uv = uv_immutable.toVar();
uv.assign((0, _OperatorNode.mul)(2.0, uv).sub(1.0));
const direction = (0, _TSLBase.vec3)(uv, 1.0).toVar();
(0, _TSLBase.If)(face.equal(0.0), () => {
direction.assign(direction.zyx); // ( 1, v, u ) pos x
}).ElseIf(face.equal(1.0), () => {
direction.assign(direction.xzy);
direction.xz.mulAssign(-1.0); // ( -u, 1, -v ) pos y
}).ElseIf(face.equal(2.0), () => {
direction.x.mulAssign(-1.0); // ( -u, v, 1 ) pos z
}).ElseIf(face.equal(3.0), () => {
direction.assign(direction.zyx);
direction.xz.mulAssign(-1.0); // ( -1, v, -u ) neg x
}).ElseIf(face.equal(4.0), () => {
direction.assign(direction.xzy);
direction.xy.mulAssign(-1.0); // ( -u, -1, v ) neg y
}).ElseIf(face.equal(5.0), () => {
direction.z.mulAssign(-1.0); // ( u, v, -1 ) neg zS
});
return direction;
}).setLayout({
name: 'getDirection',
type: 'vec3',
inputs: [{
name: 'uv',
type: 'vec2'
}, {
name: 'face',
type: 'float'
}]
});
//
const textureCubeUV = exports.textureCubeUV = /*@__PURE__*/(0, _TSLBase.Fn)(([envMap, sampleDir_immutable, roughness_immutable, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP]) => {
const roughness = (0, _TSLBase.float)(roughness_immutable);
const sampleDir = (0, _TSLBase.vec3)(sampleDir_immutable);
const mip = (0, _MathNode.clamp)(roughnessToMip(roughness), cubeUV_m0, CUBEUV_MAX_MIP);
const mipF = (0, _MathNode.fract)(mip);
const mipInt = (0, _MathNode.floor)(mip);
const color0 = (0, _TSLBase.vec3)(bilinearCubeUV(envMap, sampleDir, mipInt, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP)).toVar();
(0, _TSLBase.If)(mipF.notEqual(0.0), () => {
const color1 = (0, _TSLBase.vec3)(bilinearCubeUV(envMap, sampleDir, mipInt.add(1.0), CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP)).toVar();
color0.assign((0, _MathNode.mix)(color0, color1, mipF));
});
return color0;
});
const bilinearCubeUV = /*@__PURE__*/(0, _TSLBase.Fn)(([envMap, direction_immutable, mipInt_immutable, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP]) => {
const mipInt = (0, _TSLBase.float)(mipInt_immutable).toVar();
const direction = (0, _TSLBase.vec3)(direction_immutable);
const face = (0, _TSLBase.float)(getFace(direction)).toVar();
const filterInt = (0, _TSLBase.float)((0, _MathNode.max)(cubeUV_minMipLevel.sub(mipInt), 0.0)).toVar();
mipInt.assign((0, _MathNode.max)(mipInt, cubeUV_minMipLevel));
const faceSize = (0, _TSLBase.float)((0, _MathNode.exp2)(mipInt)).toVar();
const uv = (0, _TSLBase.vec2)(getUV(direction, face).mul(faceSize.sub(2.0)).add(1.0)).toVar();
(0, _TSLBase.If)(face.greaterThan(2.0), () => {
uv.y.addAssign(faceSize);
face.subAssign(3.0);
});
uv.x.addAssign(face.mul(faceSize));
uv.x.addAssign(filterInt.mul((0, _OperatorNode.mul)(3.0, cubeUV_minTileSize)));
uv.y.addAssign((0, _OperatorNode.mul)(4.0, (0, _MathNode.exp2)(CUBEUV_MAX_MIP).sub(faceSize)));
uv.x.mulAssign(CUBEUV_TEXEL_WIDTH);
uv.y.mulAssign(CUBEUV_TEXEL_HEIGHT);
return envMap.sample(uv).grad((0, _TSLBase.vec2)(), (0, _TSLBase.vec2)()); // disable anisotropic filtering
});
const getSample = /*@__PURE__*/(0, _TSLBase.Fn)(({
envMap,
mipInt,
outputDirection,
theta,
axis,
CUBEUV_TEXEL_WIDTH,
CUBEUV_TEXEL_HEIGHT,
CUBEUV_MAX_MIP
}) => {
const cosTheta = (0, _MathNode.cos)(theta);
// Rodrigues' axis-angle rotation
const sampleDirection = outputDirection.mul(cosTheta).add(axis.cross(outputDirection).mul((0, _MathNode.sin)(theta))).add(axis.mul(axis.dot(outputDirection).mul(cosTheta.oneMinus())));
return bilinearCubeUV(envMap, sampleDirection, mipInt, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP);
});
const blur = exports.blur = /*@__PURE__*/(0, _TSLBase.Fn)(({
n,
latitudinal,
poleAxis,
outputDirection,
weights,
samples,
dTheta,
mipInt,
envMap,
CUBEUV_TEXEL_WIDTH,
CUBEUV_TEXEL_HEIGHT,
CUBEUV_MAX_MIP
}) => {
const axis = (0, _TSLBase.vec3)((0, _ConditionalNode.select)(latitudinal, poleAxis, (0, _MathNode.cross)(poleAxis, outputDirection))).toVar();
(0, _TSLBase.If)(axis.equal((0, _TSLBase.vec3)(0.0)), () => {
axis.assign((0, _TSLBase.vec3)(outputDirection.z, 0.0, outputDirection.x.negate()));
});
axis.assign((0, _MathNode.normalize)(axis));
const gl_FragColor = (0, _TSLBase.vec3)().toVar();
gl_FragColor.addAssign(weights.element(0).mul(getSample({
theta: 0.0,
axis,
outputDirection,
mipInt,
envMap,
CUBEUV_TEXEL_WIDTH,
CUBEUV_TEXEL_HEIGHT,
CUBEUV_MAX_MIP
})));
(0, _LoopNode.Loop)({
start: (0, _TSLBase.int)(1),
end: n
}, ({
i
}) => {
(0, _TSLBase.If)(i.greaterThanEqual(samples), () => {
(0, _LoopNode.Break)();
});
const theta = (0, _TSLBase.float)(dTheta.mul((0, _TSLBase.float)(i))).toVar();
gl_FragColor.addAssign(weights.element(i).mul(getSample({
theta: theta.mul(-1.0),
axis,
outputDirection,
mipInt,
envMap,
CUBEUV_TEXEL_WIDTH,
CUBEUV_TEXEL_HEIGHT,
CUBEUV_MAX_MIP
})));
gl_FragColor.addAssign(weights.element(i).mul(getSample({
theta,
axis,
outputDirection,
mipInt,
envMap,
CUBEUV_TEXEL_WIDTH,
CUBEUV_TEXEL_HEIGHT,
CUBEUV_MAX_MIP
})));
});
return (0, _TSLBase.vec4)(gl_FragColor, 1);
});