@openhps/core
Version:
Open Hybrid Positioning System - Core component
160 lines (144 loc) • 5.63 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toonOutlinePass = exports.default = void 0;
var _TSLBase = require("../tsl/TSLBase.js");
var _Color = require("../../math/Color.js");
var _NodeMaterial = _interopRequireDefault(require("../../materials/nodes/NodeMaterial.js"));
var _Camera = require("../../nodes/accessors/Camera.js");
var _ModelNode = require("../../nodes/accessors/ModelNode.js");
var _Position = require("../../nodes/accessors/Position.js");
var _Normal = require("../../nodes/accessors/Normal.js");
var _constants = require("../../constants.js");
var _PassNode = _interopRequireDefault(require("./PassNode.js"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Represents a render pass for producing a toon outline effect on compatible objects.
* Only 3D objects with materials of type `MeshToonMaterial` and `MeshToonNodeMaterial`
* will receive the outline.
*
* ```js
* const postProcessing = new PostProcessing( renderer );
*
* const scenePass = toonOutlinePass( scene, camera );
*
* postProcessing.outputNode = scenePass;
* ```
* @augments PassNode
*/
class ToonOutlinePassNode extends _PassNode.default {
static get type() {
return 'ToonOutlinePassNode';
}
/**
* Constructs a new outline pass node.
*
* @param {Scene} scene - A reference to the scene.
* @param {Camera} camera - A reference to the camera.
* @param {Node} colorNode - Defines the outline's color.
* @param {Node} thicknessNode - Defines the outline's thickness.
* @param {Node} alphaNode - Defines the outline's alpha.
*/
constructor(scene, camera, colorNode, thicknessNode, alphaNode) {
super(_PassNode.default.COLOR, scene, camera);
/**
* Defines the outline's color.
*
* @type {Node}
*/
this.colorNode = colorNode;
/**
* Defines the outline's thickness.
*
* @type {Node}
*/
this.thicknessNode = thicknessNode;
/**
* Defines the outline's alpha.
*
* @type {Node}
*/
this.alphaNode = alphaNode;
/**
* An internal material cache.
*
* @private
* @type {WeakMap<Material, NodeMaterial>}
*/
this._materialCache = new WeakMap();
}
updateBefore(frame) {
const {
renderer
} = frame;
const currentRenderObjectFunction = renderer.getRenderObjectFunction();
renderer.setRenderObjectFunction((object, scene, camera, geometry, material, group, lightsNode, clippingContext) => {
// only render outline for supported materials
if (material.isMeshToonMaterial || material.isMeshToonNodeMaterial) {
if (material.wireframe === false) {
const outlineMaterial = this._getOutlineMaterial(material);
renderer.renderObject(object, scene, camera, geometry, outlineMaterial, group, lightsNode, clippingContext);
}
}
// default
renderer.renderObject(object, scene, camera, geometry, material, group, lightsNode, clippingContext);
});
super.updateBefore(frame);
renderer.setRenderObjectFunction(currentRenderObjectFunction);
}
/**
* Creates the material used for outline rendering.
*
* @private
* @return {NodeMaterial} The outline material.
*/
_createMaterial() {
const material = new _NodeMaterial.default();
material.isMeshToonOutlineMaterial = true;
material.name = 'Toon_Outline';
material.side = _constants.BackSide;
// vertex node
const outlineNormal = _Normal.normalLocal.negate();
const mvp = _Camera.cameraProjectionMatrix.mul(_ModelNode.modelViewMatrix);
const ratio = (0, _TSLBase.float)(1.0); // TODO: support outline thickness ratio for each vertex
const pos = mvp.mul((0, _TSLBase.vec4)(_Position.positionLocal, 1.0));
const pos2 = mvp.mul((0, _TSLBase.vec4)(_Position.positionLocal.add(outlineNormal), 1.0));
const norm = (0, _TSLBase.normalize)(pos.sub(pos2)); // NOTE: subtract pos2 from pos because BackSide objectNormal is negative
material.vertexNode = pos.add(norm.mul(this.thicknessNode).mul(pos.w).mul(ratio));
// color node
material.colorNode = (0, _TSLBase.vec4)(this.colorNode, this.alphaNode);
return material;
}
/**
* For the given toon material, this method returns a corresponding
* outline material.
*
* @private
* @param {(MeshToonMaterial|MeshToonNodeMaterial)} originalMaterial - The toon material.
* @return {NodeMaterial} The outline material.
*/
_getOutlineMaterial(originalMaterial) {
let outlineMaterial = this._materialCache.get(originalMaterial);
if (outlineMaterial === undefined) {
outlineMaterial = this._createMaterial();
this._materialCache.set(originalMaterial, outlineMaterial);
}
return outlineMaterial;
}
}
var _default = exports.default = ToonOutlinePassNode;
/**
* TSL function for creating a toon outline pass node.
*
* @tsl
* @function
* @param {Scene} scene - A reference to the scene.
* @param {Camera} camera - A reference to the camera.
* @param {Color} color - Defines the outline's color.
* @param {number} [thickness=0.003] - Defines the outline's thickness.
* @param {number} [alpha=1] - Defines the outline's alpha.
* @returns {ToonOutlinePassNode}
*/
const toonOutlinePass = (scene, camera, color = new _Color.Color(0, 0, 0), thickness = 0.003, alpha = 1) => (0, _TSLBase.nodeObject)(new ToonOutlinePassNode(scene, camera, (0, _TSLBase.nodeObject)(color), (0, _TSLBase.nodeObject)(thickness), (0, _TSLBase.nodeObject)(alpha)));
exports.toonOutlinePass = toonOutlinePass;