UNPKG

glsl-pipeline

Version:

Prototype complex pipelines directly from a single shader by branching it into stages using React Three Fiber/React.

216 lines (201 loc) 7.39 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var React = require('react'); var fiber = require('@react-three/fiber'); var vanilla = require('../../dist/vanilla-4c825a15.cjs.dev.js'); var zustand = require('zustand'); var tsMain = require('../../dist/ts-main-1ac5892d.cjs.dev.js'); require('three'); require('three/examples/jsm/loaders/RGBELoader.js'); require('three/examples/jsm/lights/LightProbeGenerator.js'); function _interopNamespace(e) { if (e && e.__esModule) return e; var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n["default"] = e; return Object.freeze(n); } var React__namespace = /*#__PURE__*/_interopNamespace(React); function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; } function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; } var GlslPipelineContext = zustand.create(function () { return {}; }); function useGlslPipeline(callback, ref) { var priority = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; var _GlslPipelineContext = GlslPipelineContext(), addCallback = _GlslPipelineContext.addCallback, removeCallback = _GlslPipelineContext.removeCallback; React__namespace.useEffect(function () { if (!callback || !addCallback || !removeCallback || !ref.current) return; addCallback(callback, priority, ref.current); return function () { removeCallback(callback); }; }, [ref.current, addCallback, removeCallback, priority]); // eslint-disable-line react-hooks/exhaustive-deps } var _excluded = ["type", "uniforms", "fragmentShader", "vertexShader", "branch", "resize", "autoRender", "renderPriority"]; var GlslPipelineReact = /* @__PURE__ */React__namespace.memo(/*#__PURE__*/React__namespace.forwardRef(function (_ref, ref) { var _ref$type = _ref.type, type = _ref$type === void 0 ? "scene" : _ref$type, uniforms = _ref.uniforms, fragmentShader = _ref.fragmentShader, vertexShader = _ref.vertexShader, branch = _ref.branch, _ref$resize = _ref.resize, resize = _ref$resize === void 0 ? true : _ref$resize, _ref$autoRender = _ref.autoRender, autoRender = _ref$autoRender === void 0 ? true : _ref$autoRender, _ref$renderPriority = _ref.renderPriority, renderPriority = _ref$renderPriority === void 0 ? 0 : _ref$renderPriority, props = _objectWithoutProperties(_ref, _excluded); var _useThree = fiber.useThree(), gl = _useThree.gl, camera = _useThree.camera, size = _useThree.size; var callbacks = React__namespace.useRef([]); var addCallback = React__namespace.useCallback(function (callback, priority, pipeline) { callbacks.current.push({ callback: callback, priority: priority, pipeline: pipeline }); callbacks.current.sort(function (a, b) { return a.priority - b.priority; }); }, []); var removeCallback = React__namespace.useCallback(function (callback) { callbacks.current = callbacks.current.filter(function (cb) { return cb.callback !== callback; }); }, []); var filtered = React__namespace.useCallback(function (pipe) { return Object.keys(pipe).reduce(function (res, key) { if (typeof pipe[key] !== 'function') { res[key] = pipe[key]; } return res; }, {}); }, []); var onRender = React__namespace.useCallback(function (s) { for (var i = 0; i < callbacks.current.length; i++) { callbacks.current[i].callback(filtered(callbacks.current[i].pipeline), s); } }, []); var pipeline = React__namespace.useMemo(function () { // Apply the same glsl if ref given the same glsl-pipeline reference var glsl; // Check if ref.current exists and instance of GlslPipeline class if (ref && ref.current instanceof vanilla.GlslPipeline) { // Assign to existing GlslPipeline glsl = ref.current; // Apply uniforms if exists if (uniforms) { glsl.uniforms = uniforms; } // Apply options if any if (props) { glsl.options = props; } } else { // Else initialized new GlslPipeline glsl = new vanilla.GlslPipeline(gl, uniforms, props); } glsl.load(fragmentShader, vertexShader); return glsl; }, [fragmentShader, vertexShader, gl, uniforms, props]); fiber.useFrame(function (state) { if (autoRender) { switch (type) { case "scene": pipeline.renderScene(state.scene, state.camera); break; case "main": pipeline.renderMain(); break; } } onRender(state); }, renderPriority); React__namespace.useEffect(function () { if (pipeline) { GlslPipelineContext.setState({ addCallback: addCallback, removeCallback: removeCallback }); } }, [addCallback, removeCallback]); var material = React__namespace.useMemo(function () { return branch ? pipeline.branchMaterial(branch) : pipeline.material; }, [pipeline, branch]); React__namespace.useImperativeHandle(ref, function () { return pipeline; }, [pipeline]); var onResize = React__namespace.useCallback(function () { if (!type) return; gl.setPixelRatio(window.devicePixelRatio); gl.setSize(size.width, size.height); pipeline.setSize(size.width, size.height); // Only set camera manually if camera set to `manual` because fiber is making the camera responsive by default. if (type === 'scene' && tsMain.isPerspectiveCamera(camera)) { camera.aspect = size.width / size.height; camera.updateProjectionMatrix(); } }, [pipeline, type, size, camera, gl]); React__namespace.useLayoutEffect(function () { if (resize) { window.addEventListener('resize', onResize, false); onResize(); } return function () { if (resize) { window.removeEventListener('resize', onResize, false); } pipeline.dispose(); }; }, [resize, onResize, pipeline]); return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, type === 'scene' ? /*#__PURE__*/React__namespace.createElement("primitive", { ref: ref, attach: "material", object: material }) : type === 'main' && /*#__PURE__*/React__namespace.createElement("mesh", null, /*#__PURE__*/React__namespace.createElement("planeGeometry", { args: [2, 2] }), /*#__PURE__*/React__namespace.createElement("primitive", { ref: ref, attach: "material", object: material }))); })); // For React Dev Tools Display Name GlslPipelineReact.displayName = 'GlslPipelineReact'; exports.GlslPipelineContext = GlslPipelineContext; exports.GlslPipelineReact = GlslPipelineReact; exports.useGlslPipeline = useGlslPipeline;