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
JavaScript
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;
;