(function (global, factory) { if (typeof define === "function" && define.amd) { define(["exports", "./constants.js", "three"], factory); } else if (typeof exports !== "undefined") { factory(exports, require("./constants.js"), require("three")); } else { var mod = { exports: {} }; factory(mod.exports, global.constants, global.three); global.WebGPURenderPipeline = mod.exports; } })(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports, _constants, _three) { "use strict"; Object.defineProperty(_exports, "__esModule", { value: true }); _exports.default = void 0; function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } var WebGPURenderPipeline = /*#__PURE__*/function () { function WebGPURenderPipeline(device, renderer, sampleCount) { _classCallCheck(this, WebGPURenderPipeline); this.cacheKey = null; this.shaderAttributes = null; this.stageVertex = null; this.stageFragment = null; this.usedTimes = 0; this._device = device; this._renderer = renderer; this._sampleCount = sampleCount; } _createClass(WebGPURenderPipeline, [{ key: "init", value: function init(cacheKey, stageVertex, stageFragment, object, nodeBuilder) { var material = object.material; var geometry = object.geometry; // determine shader attributes var shaderAttributes = this._getShaderAttributes(nodeBuilder, geometry); // vertex buffers var vertexBuffers = []; var _iterator = _createForOfIteratorHelper(shaderAttributes), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var attribute = _step.value; var name = attribute.name; var geometryAttribute = geometry.getAttribute(name); var stepMode = geometryAttribute !== undefined && geometryAttribute.isInstancedBufferAttribute ? _constants.GPUInputStepMode.Instance : _constants.GPUInputStepMode.Vertex; vertexBuffers.push({ arrayStride: attribute.arrayStride, attributes: [{ shaderLocation: attribute.slot, offset: 0, format: attribute.format }], stepMode: stepMode }); } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } this.cacheKey = cacheKey; this.shaderAttributes = shaderAttributes; this.stageVertex = stageVertex; this.stageFragment = stageFragment; // blending var alphaBlend = {}; var colorBlend = {}; if (material.transparent === true && material.blending !== _three.NoBlending) { alphaBlend = this._getAlphaBlend(material); colorBlend = this._getColorBlend(material); } // stencil var stencilFront = {}; if (material.stencilWrite === true) { stencilFront = { compare: this._getStencilCompare(material), failOp: this._getStencilOperation(material.stencilFail), depthFailOp: this._getStencilOperation(material.stencilZFail), passOp: this._getStencilOperation(material.stencilZPass) }; } // var primitiveState = this._getPrimitiveState(object, material); var colorWriteMask = this._getColorWriteMask(material); var depthCompare = this._getDepthCompare(material); var colorFormat = this._renderer.getCurrentColorFormat(); var depthStencilFormat = this._renderer.getCurrentDepthStencilFormat(); this.pipeline = this._device.createRenderPipeline({ vertex: Object.assign({}, stageVertex.stage, { buffers: vertexBuffers }), fragment: Object.assign({}, stageFragment.stage, { targets: [{ format: colorFormat, blend: { alpha: alphaBlend, color: colorBlend }, writeMask: colorWriteMask }] }), primitive: primitiveState, depthStencil: { format: depthStencilFormat, depthWriteEnabled: material.depthWrite, depthCompare: depthCompare, stencilFront: stencilFront, stencilBack: {}, // three.js does not provide an API to configure the back function (gl.stencilFuncSeparate() was never used) stencilReadMask: material.stencilFuncMask, stencilWriteMask: material.stencilWriteMask }, multisample: { count: this._sampleCount } }); } }, { key: "_getArrayStride", value: function _getArrayStride(type, bytesPerElement) { // @TODO: This code is GLSL specific. We need to update when we switch to WGSL. if (type === 'float' || type === 'int' || type === 'uint') return bytesPerElement; if (type === 'vec2' || type === 'ivec2' || type === 'uvec2') return bytesPerElement * 2; if (type === 'vec3' || type === 'ivec3' || type === 'uvec3') return bytesPerElement * 3; if (type === 'vec4' || type === 'ivec4' || type === 'uvec4') return bytesPerElement * 4; console.error('THREE.WebGPURenderer: Shader variable type not supported yet.', type); } }, { key: "_getAlphaBlend", value: function _getAlphaBlend(material) { var blending = material.blending; var premultipliedAlpha = material.premultipliedAlpha; var alphaBlend = undefined; switch (blending) { case _three.NormalBlending: if (premultipliedAlpha === false) { alphaBlend = { srcFactor: _constants.GPUBlendFactor.One, dstFactor: _constants.GPUBlendFactor.OneMinusSrcAlpha, operation: _constants.GPUBlendOperation.Add }; } break; case _three.AdditiveBlending: // no alphaBlend settings break; case _three.SubtractiveBlending: if (premultipliedAlpha === true) { alphaBlend = { srcFactor: _constants.GPUBlendFactor.OneMinusSrcColor, dstFactor: _constants.GPUBlendFactor.OneMinusSrcAlpha, operation: _constants.GPUBlendOperation.Add }; } break; case _three.MultiplyBlending: if (premultipliedAlpha === true) { alphaBlend = { srcFactor: _constants.GPUBlendFactor.Zero, dstFactor: _constants.GPUBlendFactor.SrcAlpha, operation: _constants.GPUBlendOperation.Add }; } break; case _three.CustomBlending: var blendSrcAlpha = material.blendSrcAlpha; var blendDstAlpha = material.blendDstAlpha; var blendEquationAlpha = material.blendEquationAlpha; if (blendSrcAlpha !== null && blendDstAlpha !== null && blendEquationAlpha !== null) { alphaBlend = { srcFactor: this._getBlendFactor(blendSrcAlpha), dstFactor: this._getBlendFactor(blendDstAlpha), operation: this._getBlendOperation(blendEquationAlpha) }; } break; default: console.error('THREE.WebGPURenderer: Blending not supported.', blending); } return alphaBlend; } }, { key: "_getBlendFactor", value: function _getBlendFactor(blend) { var blendFactor; switch (blend) { case _three.ZeroFactor: blendFactor = _constants.GPUBlendFactor.Zero; break; case _three.OneFactor: blendFactor = _constants.GPUBlendFactor.One; break; case _three.SrcColorFactor: blendFactor = _constants.GPUBlendFactor.SrcColor; break; case _three.OneMinusSrcColorFactor: blendFactor = _constants.GPUBlendFactor.OneMinusSrcColor; break; case _three.SrcAlphaFactor: blendFactor = _constants.GPUBlendFactor.SrcAlpha; break; case _three.OneMinusSrcAlphaFactor: blendFactor = _constants.GPUBlendFactor.OneMinusSrcAlpha; break; case _three.DstColorFactor: blendFactor = _constants.GPUBlendFactor.DstColor; break; case _three.OneMinusDstColorFactor: blendFactor = _constants.GPUBlendFactor.OneMinusDstColor; break; case _three.DstAlphaFactor: blendFactor = _constants.GPUBlendFactor.DstAlpha; break; case _three.OneMinusDstAlphaFactor: blendFactor = _constants.GPUBlendFactor.OneMinusDstAlpha; break; case _three.SrcAlphaSaturateFactor: blendFactor = _constants.GPUBlendFactor.SrcAlphaSaturated; break; case _constants.BlendColorFactor: blendFactor = _constants.GPUBlendFactor.BlendColor; break; case _constants.OneMinusBlendColorFactor: blendFactor = _constants.GPUBlendFactor.OneMinusBlendColor; break; default: console.error('THREE.WebGPURenderer: Blend factor not supported.', blend); } return blendFactor; } }, { key: "_getBlendOperation", value: function _getBlendOperation(blendEquation) { var blendOperation; switch (blendEquation) { case _three.AddEquation: blendOperation = _constants.GPUBlendOperation.Add; break; case _three.SubtractEquation: blendOperation = _constants.GPUBlendOperation.Subtract; break; case _three.ReverseSubtractEquation: blendOperation = _constants.GPUBlendOperation.ReverseSubtract; break; case _three.MinEquation: blendOperation = _constants.GPUBlendOperation.Min; break; case _three.MaxEquation: blendOperation = _constants.GPUBlendOperation.Max; break; default: console.error('THREE.WebGPURenderer: Blend equation not supported.', blendEquation); } return blendOperation; } }, { key: "_getColorBlend", value: function _getColorBlend(material) { var blending = material.blending; var premultipliedAlpha = material.premultipliedAlpha; var colorBlend = { srcFactor: null, dstFactor: null, operation: null }; switch (blending) { case _three.NormalBlending: colorBlend.srcFactor = premultipliedAlpha === true ? _constants.GPUBlendFactor.One : _constants.GPUBlendFactor.SrcAlpha; colorBlend.dstFactor = _constants.GPUBlendFactor.OneMinusSrcAlpha; colorBlend.operation = _constants.GPUBlendOperation.Add; break; case _three.AdditiveBlending: colorBlend.srcFactor = premultipliedAlpha === true ? _constants.GPUBlendFactor.One : _constants.GPUBlendFactor.SrcAlpha; colorBlend.operation = _constants.GPUBlendOperation.Add; break; case _three.SubtractiveBlending: colorBlend.srcFactor = _constants.GPUBlendFactor.Zero; colorBlend.dstFactor = premultipliedAlpha === true ? _constants.GPUBlendFactor.Zero : _constants.GPUBlendFactor.OneMinusSrcColor; colorBlend.operation = _constants.GPUBlendOperation.Add; break; case _three.MultiplyBlending: colorBlend.srcFactor = _constants.GPUBlendFactor.Zero; colorBlend.dstFactor = _constants.GPUBlendFactor.SrcColor; colorBlend.operation = _constants.GPUBlendOperation.Add; break; case _three.CustomBlending: colorBlend.srcFactor = this._getBlendFactor(material.blendSrc); colorBlend.dstFactor = this._getBlendFactor(material.blendDst); colorBlend.operation = this._getBlendOperation(material.blendEquation); break; default: console.error('THREE.WebGPURenderer: Blending not supported.', blending); } return colorBlend; } }, { key: "_getColorWriteMask", value: function _getColorWriteMask(material) { return material.colorWrite === true ? _constants.GPUColorWriteFlags.All : _constants.GPUColorWriteFlags.None; } }, { key: "_getDepthCompare", value: function _getDepthCompare(material) { var depthCompare; if (material.depthTest === false) { depthCompare = _constants.GPUCompareFunction.Always; } else { var depthFunc = material.depthFunc; switch (depthFunc) { case _three.NeverDepth: depthCompare = _constants.GPUCompareFunction.Never; break; case _three.AlwaysDepth: depthCompare = _constants.GPUCompareFunction.Always; break; case _three.LessDepth: depthCompare = _constants.GPUCompareFunction.Less; break; case _three.LessEqualDepth: depthCompare = _constants.GPUCompareFunction.LessEqual; break; case _three.EqualDepth: depthCompare = _constants.GPUCompareFunction.Equal; break; case _three.GreaterEqualDepth: depthCompare = _constants.GPUCompareFunction.GreaterEqual; break; case _three.GreaterDepth: depthCompare = _constants.GPUCompareFunction.Greater; break; case _three.NotEqualDepth: depthCompare = _constants.GPUCompareFunction.NotEqual; break; default: console.error('THREE.WebGPURenderer: Invalid depth function.', depthFunc); } } return depthCompare; } }, { key: "_getPrimitiveState", value: function _getPrimitiveState(object, material) { var descriptor = {}; descriptor.topology = this._getPrimitiveTopology(object); if (object.isLine === true && object.isLineSegments !== true) { var geometry = object.geometry; var count = geometry.index ? geometry.index.count : geometry.attributes.position.count; descriptor.stripIndexFormat = count > 65535 ? _constants.GPUIndexFormat.Uint32 : _constants.GPUIndexFormat.Uint16; // define data type for primitive restart value } switch (material.side) { case _three.FrontSide: descriptor.frontFace = _constants.GPUFrontFace.CCW; descriptor.cullMode = _constants.GPUCullMode.Back; break; case _three.BackSide: descriptor.frontFace = _constants.GPUFrontFace.CW; descriptor.cullMode = _constants.GPUCullMode.Back; break; case _three.DoubleSide: descriptor.frontFace = _constants.GPUFrontFace.CCW; descriptor.cullMode = _constants.GPUCullMode.None; break; default: console.error('THREE.WebGPURenderer: Unknown Material.side value.', material.side); break; } return descriptor; } }, { key: "_getPrimitiveTopology", value: function _getPrimitiveTopology(object) { if (object.isMesh) return _constants.GPUPrimitiveTopology.TriangleList;else if (object.isPoints) return _constants.GPUPrimitiveTopology.PointList;else if (object.isLineSegments) return _constants.GPUPrimitiveTopology.LineList;else if (object.isLine) return _constants.GPUPrimitiveTopology.LineStrip; } }, { key: "_getStencilCompare", value: function _getStencilCompare(material) { var stencilCompare; var stencilFunc = material.stencilFunc; switch (stencilFunc) { case _three.NeverStencilFunc: stencilCompare = _constants.GPUCompareFunction.Never; break; case _three.AlwaysStencilFunc: stencilCompare = _constants.GPUCompareFunction.Always; break; case _three.LessStencilFunc: stencilCompare = _constants.GPUCompareFunction.Less; break; case _three.LessEqualStencilFunc: stencilCompare = _constants.GPUCompareFunction.LessEqual; break; case _three.EqualStencilFunc: stencilCompare = _constants.GPUCompareFunction.Equal; break; case _three.GreaterEqualStencilFunc: stencilCompare = _constants.GPUCompareFunction.GreaterEqual; break; case _three.GreaterStencilFunc: stencilCompare = _constants.GPUCompareFunction.Greater; break; case _three.NotEqualStencilFunc: stencilCompare = _constants.GPUCompareFunction.NotEqual; break; default: console.error('THREE.WebGPURenderer: Invalid stencil function.', stencilFunc); } return stencilCompare; } }, { key: "_getStencilOperation", value: function _getStencilOperation(op) { var stencilOperation; switch (op) { case _three.KeepStencilOp: stencilOperation = _constants.GPUStencilOperation.Keep; break; case _three.ZeroStencilOp: stencilOperation = _constants.GPUStencilOperation.Zero; break; case _three.ReplaceStencilOp: stencilOperation = _constants.GPUStencilOperation.Replace; break; case _three.InvertStencilOp: stencilOperation = _constants.GPUStencilOperation.Invert; break; case _three.IncrementStencilOp: stencilOperation = _constants.GPUStencilOperation.IncrementClamp; break; case _three.DecrementStencilOp: stencilOperation = _constants.GPUStencilOperation.DecrementClamp; break; case _three.IncrementWrapStencilOp: stencilOperation = _constants.GPUStencilOperation.IncrementWrap; break; case _three.DecrementWrapStencilOp: stencilOperation = _constants.GPUStencilOperation.DecrementWrap; break; default: console.error('THREE.WebGPURenderer: Invalid stencil operation.', stencilOperation); } return stencilOperation; } }, { key: "_getVertexFormat", value: function _getVertexFormat(type, bytesPerElement) { // float if (type === 'float') return _constants.GPUVertexFormat.Float32; if (type === 'vec2') { if (bytesPerElement === 2) { return _constants.GPUVertexFormat.Float16x2; } else { return _constants.GPUVertexFormat.Float32x2; } } if (type === 'vec3') return _constants.GPUVertexFormat.Float32x3; if (type === 'vec4') { if (bytesPerElement === 2) { return _constants.GPUVertexFormat.Float16x4; } else { return _constants.GPUVertexFormat.Float32x4; } } // int if (type === 'int') return _constants.GPUVertexFormat.Sint32; if (type === 'ivec2') { if (bytesPerElement === 1) { return _constants.GPUVertexFormat.Sint8x2; } else if (bytesPerElement === 2) { return _constants.GPUVertexFormat.Sint16x2; } else { return _constants.GPUVertexFormat.Sint32x2; } } if (type === 'ivec3') return _constants.GPUVertexFormat.Sint32x3; if (type === 'ivec4') { if (bytesPerElement === 1) { return _constants.GPUVertexFormat.Sint8x4; } else if (bytesPerElement === 2) { return _constants.GPUVertexFormat.Sint16x4; } else { return _constants.GPUVertexFormat.Sint32x4; } } // uint if (type === 'uint') return _constants.GPUVertexFormat.Uint32; if (type === 'uvec2') { if (bytesPerElement === 1) { return _constants.GPUVertexFormat.Uint8x2; } else if (bytesPerElement === 2) { return _constants.GPUVertexFormat.Uint16x2; } else { return _constants.GPUVertexFormat.Uint32x2; } } if (type === 'uvec3') return _constants.GPUVertexFormat.Uint32x3; if (type === 'uvec4') { if (bytesPerElement === 1) { return _constants.GPUVertexFormat.Uint8x4; } else if (bytesPerElement === 2) { return _constants.GPUVertexFormat.Uint16x4; } else { return _constants.GPUVertexFormat.Uint32x4; } } console.error('THREE.WebGPURenderer: Shader variable type not supported yet.', type); } }, { key: "_getShaderAttributes", value: function _getShaderAttributes(nodeBuilder, geometry) { var nodeAttributes = nodeBuilder.attributes; var attributes = []; for (var slot = 0; slot < nodeAttributes.length; slot++) { var nodeAttribute = nodeAttributes[slot]; var name = nodeAttribute.name; var type = nodeAttribute.type; var geometryAttribute = geometry.getAttribute(name); var bytesPerElement = geometryAttribute !== undefined ? geometryAttribute.array.BYTES_PER_ELEMENT : 4; var arrayStride = this._getArrayStride(type, bytesPerElement); var format = this._getVertexFormat(type, bytesPerElement); attributes.push({ name: name, arrayStride: arrayStride, format: format, slot: slot }); } return attributes; } }]); return WebGPURenderPipeline; }(); var _default = WebGPURenderPipeline; _exports.default = _default; });