(function (global, factory) {
  if (typeof define === "function" && define.amd) {
    define(["exports", "../core/TempNode.js", "../core/ConstNode.js", "../core/StructNode.js", "../core/FunctionNode.js", "../core/FunctionCallNode.js", "../core/ExpressionNode.js", "../inputs/FloatNode.js", "../math/OperatorNode.js", "../math/MathNode.js", "../utils/ColorSpaceNode.js"], factory);
  } else if (typeof exports !== "undefined") {
    factory(exports, require("../core/TempNode.js"), require("../core/ConstNode.js"), require("../core/StructNode.js"), require("../core/FunctionNode.js"), require("../core/FunctionCallNode.js"), require("../core/ExpressionNode.js"), require("../inputs/FloatNode.js"), require("../math/OperatorNode.js"), require("../math/MathNode.js"), require("../utils/ColorSpaceNode.js"));
  } else {
    var mod = {
      exports: {}
    };
    factory(mod.exports, global.TempNode, global.ConstNode, global.StructNode, global.FunctionNode, global.FunctionCallNode, global.ExpressionNode, global.FloatNode, global.OperatorNode, global.MathNode, global.ColorSpaceNode);
    global.TextureCubeUVNode = mod.exports;
  }
})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports, _TempNode2, _ConstNode, _StructNode, _FunctionNode, _FunctionCallNode, _ExpressionNode, _FloatNode, _OperatorNode, _MathNode, _ColorSpaceNode) {
  "use strict";

  Object.defineProperty(_exports, "__esModule", {
    value: true
  });
  _exports.TextureCubeUVNode = void 0;

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

  function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } Object.defineProperty(subClass, "prototype", { value: Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }), writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }

  function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

  function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }

  function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }

  function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

  function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }

  function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

  var TextureCubeUVNode = /*#__PURE__*/function (_TempNode) {
    _inherits(TextureCubeUVNode, _TempNode);

    var _super = _createSuper(TextureCubeUVNode);

    function TextureCubeUVNode(value, uv, bias) {
      var _this;

      _classCallCheck(this, TextureCubeUVNode);

      _this = _super.call(this, 'v4');
      _this.value = value, _this.uv = uv;
      _this.bias = bias;
      return _this;
    }

    _createClass(TextureCubeUVNode, [{
      key: "bilinearCubeUV",
      value: function bilinearCubeUV(builder, texture, uv, mipInt) {
        var bilinearCubeUV = new _FunctionCallNode.FunctionCallNode(TextureCubeUVNode.Nodes.bilinearCubeUV, [texture, uv, mipInt]);
        this.colorSpaceTL = this.colorSpaceTL || new _ColorSpaceNode.ColorSpaceNode(new _ExpressionNode.ExpressionNode('', 'v4'));
        this.colorSpaceTL.fromDecoding(builder.getTextureEncodingFromMap(this.value.value));
        this.colorSpaceTL.input.parse(bilinearCubeUV.build(builder) + '.tl');
        this.colorSpaceTR = this.colorSpaceTR || new _ColorSpaceNode.ColorSpaceNode(new _ExpressionNode.ExpressionNode('', 'v4'));
        this.colorSpaceTR.fromDecoding(builder.getTextureEncodingFromMap(this.value.value));
        this.colorSpaceTR.input.parse(bilinearCubeUV.build(builder) + '.tr');
        this.colorSpaceBL = this.colorSpaceBL || new _ColorSpaceNode.ColorSpaceNode(new _ExpressionNode.ExpressionNode('', 'v4'));
        this.colorSpaceBL.fromDecoding(builder.getTextureEncodingFromMap(this.value.value));
        this.colorSpaceBL.input.parse(bilinearCubeUV.build(builder) + '.bl');
        this.colorSpaceBR = this.colorSpaceBR || new _ColorSpaceNode.ColorSpaceNode(new _ExpressionNode.ExpressionNode('', 'v4'));
        this.colorSpaceBR.fromDecoding(builder.getTextureEncodingFromMap(this.value.value));
        this.colorSpaceBR.input.parse(bilinearCubeUV.build(builder) + '.br'); // add a custom context for fix incompatibility with the core
        // include ColorSpace function only for vertex shader (in fragment shader color space functions is added automatically by core)
        // this should be removed in the future
        // context.include =: is used to include or not functions if used FunctionNode
        // context.ignoreCache =: not create temp variables nodeT0..9 to optimize the code

        var context = {
          include: builder.isShader('vertex'),
          ignoreCache: true
        };
        builder.addContext(context);
        this.colorSpaceTLExp = new _ExpressionNode.ExpressionNode(this.colorSpaceTL.build(builder, 'v4'), 'v4');
        this.colorSpaceTRExp = new _ExpressionNode.ExpressionNode(this.colorSpaceTR.build(builder, 'v4'), 'v4');
        this.colorSpaceBLExp = new _ExpressionNode.ExpressionNode(this.colorSpaceBL.build(builder, 'v4'), 'v4');
        this.colorSpaceBRExp = new _ExpressionNode.ExpressionNode(this.colorSpaceBR.build(builder, 'v4'), 'v4'); // end custom context

        builder.removeContext(); // --

        var output = new _ExpressionNode.ExpressionNode('mix( mix( cubeUV_TL, cubeUV_TR, cubeUV.f.x ), mix( cubeUV_BL, cubeUV_BR, cubeUV.f.x ), cubeUV.f.y )', 'v4');
        output.keywords['cubeUV_TL'] = this.colorSpaceTLExp;
        output.keywords['cubeUV_TR'] = this.colorSpaceTRExp;
        output.keywords['cubeUV_BL'] = this.colorSpaceBLExp;
        output.keywords['cubeUV_BR'] = this.colorSpaceBRExp;
        output.keywords['cubeUV'] = bilinearCubeUV;
        return output;
      }
    }, {
      key: "generate",
      value: function generate(builder, output) {
        if (builder.isShader('fragment')) {
          var uv = this.uv;
          var bias = this.bias || builder.context.roughness;
          var mipV = new _FunctionCallNode.FunctionCallNode(TextureCubeUVNode.Nodes.roughnessToMip, [bias]);
          var mip = new _MathNode.MathNode(mipV, TextureCubeUVNode.Nodes.m0, TextureCubeUVNode.Nodes.cubeUV_maxMipLevel, _MathNode.MathNode.CLAMP);
          var mipInt = new _MathNode.MathNode(mip, _MathNode.MathNode.FLOOR);
          var mipF = new _MathNode.MathNode(mip, _MathNode.MathNode.FRACT);
          var color0 = this.bilinearCubeUV(builder, this.value, uv, mipInt);
          var color1 = this.bilinearCubeUV(builder, this.value, uv, new _OperatorNode.OperatorNode(mipInt, new _FloatNode.FloatNode(1).setReadonly(true), _OperatorNode.OperatorNode.ADD));
          var color1Mix = new _MathNode.MathNode(color0, color1, mipF, _MathNode.MathNode.MIX);
          /*
          // TODO: Optimize this in the future
          let cond = new CondNode(
          	mipF,
          	new FloatNode( 0 ).setReadonly( true ),
          	CondNode.EQUAL,
          	color0, // if
          	color1Mix	// else
          );
          */

          return builder.format(color1Mix.build(builder), 'v4', output);
        } else {
          console.warn('THREE.TextureCubeUVNode is not compatible with ' + builder.shader + ' shader.');
          return builder.format('vec4( 0.0 )', this.getType(builder), output);
        }
      }
    }, {
      key: "toJSON",
      value: function toJSON(meta) {
        var data = this.getJSONNode(meta);

        if (!data) {
          data = this.createJSONNode(meta);
          data.value = this.value.toJSON(meta).uuid;
          data.uv = this.uv.toJSON(meta).uuid;
          data.bias = this.bias.toJSON(meta).uuid;
        }

        return data;
      }
    }]);

    return TextureCubeUVNode;
  }(_TempNode2.TempNode);

  _exports.TextureCubeUVNode = TextureCubeUVNode;

  TextureCubeUVNode.Nodes = function () {
    var TextureCubeUVData = new _StructNode.StructNode("struct TextureCubeUVData {\n\t\t\tvec4 tl;\n\t\t\tvec4 tr;\n\t\t\tvec4 br;\n\t\t\tvec4 bl;\n\t\t\tvec2 f;\n\t\t}");
    var cubeUV_maxMipLevel = new _ConstNode.ConstNode('float cubeUV_maxMipLevel 8.0', true);
    var cubeUV_minMipLevel = new _ConstNode.ConstNode('float cubeUV_minMipLevel 4.0', true);
    var cubeUV_maxTileSize = new _ConstNode.ConstNode('float cubeUV_maxTileSize 256.0', true);
    var cubeUV_minTileSize = new _ConstNode.ConstNode('float cubeUV_minTileSize 16.0', true); // 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).

    var getFace = new _FunctionNode.FunctionNode("float getFace(vec3 direction) {\n\t\t\t\tvec3 absDirection = abs(direction);\n\t\t\t\tfloat face = -1.0;\n\t\t\t\tif (absDirection.x > absDirection.z) {\n\t\t\t\t\tif (absDirection.x > absDirection.y)\n\t\t\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\t\t\telse\n\t\t\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t\t\t} else {\n\t\t\t\t\tif (absDirection.z > absDirection.y)\n\t\t\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\t\t\telse\n\t\t\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t\t\t}\n\t\t\t\treturn face;\n\t\t}");
    getFace.useKeywords = false;
    var getUV = new _FunctionNode.FunctionNode("vec2 getUV(vec3 direction, float face) {\n\t\t\t\tvec2 uv;\n\t\t\t\tif (face == 0.0) {\n\t\t\t\t\tuv = vec2(direction.z, direction.y) / abs(direction.x); // pos x\n\t\t\t\t} else if (face == 1.0) {\n\t\t\t\t\tuv = vec2(-direction.x, -direction.z) / abs(direction.y); // pos y\n\t\t\t\t} else if (face == 2.0) {\n\t\t\t\t\tuv = vec2(-direction.x, direction.y) / abs(direction.z); // pos z\n\t\t\t\t} else if (face == 3.0) {\n\t\t\t\t\tuv = vec2(-direction.z, direction.y) / abs(direction.x); // neg x\n\t\t\t\t} else if (face == 4.0) {\n\t\t\t\t\tuv = vec2(-direction.x, direction.z) / abs(direction.y); // neg y\n\t\t\t\t} else {\n\t\t\t\t\tuv = vec2(direction.x, direction.y) / abs(direction.z); // neg z\n\t\t\t\t}\n\t\t\t\treturn 0.5 * (uv + 1.0);\n\t\t}");
    getUV.useKeywords = false;
    var bilinearCubeUV = new _FunctionNode.FunctionNode("TextureCubeUVData bilinearCubeUV(sampler2D envMap, vec3 direction, float mipInt) {\n\n\t\t\tfloat face = getFace(direction);\n\t\t\tfloat filterInt = max(cubeUV_minMipLevel - mipInt, 0.0);\n\t\t\tmipInt = max(mipInt, cubeUV_minMipLevel);\n\t\t\tfloat faceSize = exp2(mipInt);\n\n\t\t\tfloat texelSize = 1.0 / (3.0 * cubeUV_maxTileSize);\n\n\t\t\tvec2 uv = getUV(direction, face) * (faceSize - 1.0);\n\t\t\tvec2 f = fract(uv);\n\t\t\tuv += 0.5 - f;\n\t\t\tif (face > 2.0) {\n\t\t\t\tuv.y += faceSize;\n\t\t\t\tface -= 3.0;\n\t\t\t}\n\t\t\tuv.x += face * faceSize;\n\t\t\tif(mipInt < cubeUV_maxMipLevel){\n\t\t\t\tuv.y += 2.0 * cubeUV_maxTileSize;\n\t\t\t}\n\t\t\tuv.y += filterInt * 2.0 * cubeUV_minTileSize;\n\t\t\tuv.x += 3.0 * max(0.0, cubeUV_maxTileSize - 2.0 * faceSize);\n\t\t\tuv *= texelSize;\n\n\t\t\tvec4 tl = texture2D(envMap, uv);\n\t\t\tuv.x += texelSize;\n\t\t\tvec4 tr = texture2D(envMap, uv);\n\t\t\tuv.y += texelSize;\n\t\t\tvec4 br = texture2D(envMap, uv);\n\t\t\tuv.x -= texelSize;\n\t\t\tvec4 bl = texture2D(envMap, uv);\n\n\t\t\treturn TextureCubeUVData( tl, tr, br, bl, f );\n\t\t}", [TextureCubeUVData, getFace, getUV, cubeUV_maxMipLevel, cubeUV_minMipLevel, cubeUV_maxTileSize, cubeUV_minTileSize]);
    bilinearCubeUV.useKeywords = false; // These defines must match with PMREMGenerator

    var r0 = new _ConstNode.ConstNode('float r0 1.0', true);
    var v0 = new _ConstNode.ConstNode('float v0 0.339', true);
    var m0 = new _ConstNode.ConstNode('float m0 -2.0', true);
    var r1 = new _ConstNode.ConstNode('float r1 0.8', true);
    var v1 = new _ConstNode.ConstNode('float v1 0.276', true);
    var m1 = new _ConstNode.ConstNode('float m1 -1.0', true);
    var r4 = new _ConstNode.ConstNode('float r4 0.4', true);
    var v4 = new _ConstNode.ConstNode('float v4 0.046', true);
    var m4 = new _ConstNode.ConstNode('float m4 2.0', true);
    var r5 = new _ConstNode.ConstNode('float r5 0.305', true);
    var v5 = new _ConstNode.ConstNode('float v5 0.016', true);
    var m5 = new _ConstNode.ConstNode('float m5 3.0', true);
    var r6 = new _ConstNode.ConstNode('float r6 0.21', true);
    var v6 = new _ConstNode.ConstNode('float v6 0.0038', true);
    var m6 = new _ConstNode.ConstNode('float m6 4.0', true);
    var defines = [r0, v0, m0, r1, v1, m1, r4, v4, m4, r5, v5, m5, r6, v6, m6];
    var roughnessToMip = new _FunctionNode.FunctionNode("float roughnessToMip(float roughness) {\n\t\t\tfloat mip = 0.0;\n\t\t\tif (roughness >= r1) {\n\t\t\t\tmip = (r0 - roughness) * (m1 - m0) / (r0 - r1) + m0;\n\t\t\t} else if (roughness >= r4) {\n\t\t\t\tmip = (r1 - roughness) * (m4 - m1) / (r1 - r4) + m1;\n\t\t\t} else if (roughness >= r5) {\n\t\t\t\tmip = (r4 - roughness) * (m5 - m4) / (r4 - r5) + m4;\n\t\t\t} else if (roughness >= r6) {\n\t\t\t\tmip = (r5 - roughness) * (m6 - m5) / (r5 - r6) + m5;\n\t\t\t} else {\n\t\t\t\tmip = -2.0 * log2(1.16 * roughness);// 1.16 = 1.79^0.25\n\t\t\t}\n\t\t\treturn mip;\n\t\t}", defines);
    return {
      bilinearCubeUV: bilinearCubeUV,
      roughnessToMip: roughnessToMip,
      m0: m0,
      cubeUV_maxMipLevel: cubeUV_maxMipLevel
    };
  }();

  TextureCubeUVNode.prototype.nodeType = 'TextureCubeUV';
});