@luma.gl/shadertools 9.1.0-beta.1 → 9.1.0-beta.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/dist.dev.js CHANGED
@@ -707,6 +707,7 @@ ${DECLARATION_INJECT_MARKER}
707
707
  }
708
708
  function assembleShaderGLSL(platformInfo, options) {
709
709
  const {
710
+ id,
710
711
  source,
711
712
  stage,
712
713
  language = "glsl",
@@ -736,6 +737,7 @@ ${DECLARATION_INJECT_MARKER}
736
737
  assembledSource = prologue ? `${sourceVersionDirective}
737
738
 
738
739
  // ----- PROLOGUE -------------------------
740
+ ${getShaderNameDefine({ id, source, stage })}
739
741
  ${`#define SHADER_TYPE_${stage.toUpperCase()}`}
740
742
 
741
743
  ${getPlatformShaderDefines(platformInfo)}
@@ -804,7 +806,7 @@ ${getApplicationDefines(allDefines)}
804
806
  return assembledSource.trim();
805
807
  }
806
808
  function assembleGetUniforms(modules) {
807
- return function getUniforms9(opts) {
809
+ return function getUniforms8(opts) {
808
810
  const uniforms = {};
809
811
  for (const module of modules) {
810
812
  const moduleUniforms = module.getUniforms?.(opts, uniforms);
@@ -813,6 +815,12 @@ ${getApplicationDefines(allDefines)}
813
815
  return uniforms;
814
816
  };
815
817
  }
818
+ function getShaderNameDefine(options) {
819
+ const { id, source, stage } = options;
820
+ const injectShaderName = id && source.indexOf("SHADER_NAME") === -1;
821
+ return injectShaderName ? `
822
+ #define SHADER_NAME ${id}_${stage}` : "";
823
+ }
816
824
  function getApplicationDefines(defines = {}) {
817
825
  let sourceText = "";
818
826
  for (const define in defines) {
@@ -929,7 +937,7 @@ ${getApplicationDefines(allDefines)}
929
937
  assembleWGSLShader(props) {
930
938
  const modules = this._getModuleList(props.modules);
931
939
  const hookFunctions = this._hookFunctions;
932
- const { source, getUniforms: getUniforms9 } = assembleWGSLShader({
940
+ const { source, getUniforms: getUniforms8 } = assembleWGSLShader({
933
941
  ...props,
934
942
  // @ts-expect-error
935
943
  source: props.source,
@@ -937,7 +945,7 @@ ${getApplicationDefines(allDefines)}
937
945
  hookFunctions
938
946
  });
939
947
  const preprocessedSource = props.platformInfo.shaderLanguage === "wgsl" ? preprocess(source) : source;
940
- return { source: preprocessedSource, getUniforms: getUniforms9, modules };
948
+ return { source: preprocessedSource, getUniforms: getUniforms8, modules };
941
949
  }
942
950
  /**
943
951
  * Assemble a pair of shaders into a single shader program
@@ -6662,2160 +6670,2162 @@ float tan_fp32(float a) {
6662
6670
  vs: fp32shader
6663
6671
  };
6664
6672
 
6665
- // src/modules/engine/picking/picking.ts
6666
- var DEFAULT_HIGHLIGHT_COLOR = [0, 1, 1, 1];
6667
- var vs = (
6673
+ // src/modules/math/fp64/fp64-arithmetic-glsl.ts
6674
+ var fp64arithmeticShader = (
6668
6675
  /* glsl */
6669
- `uniform pickingUniforms {
6670
- float isActive;
6671
- float isAttribute;
6672
- float isHighlightActive;
6673
- float useFloatColors;
6674
- vec3 highlightedObjectColor;
6675
- vec4 highlightColor;
6676
- } picking;
6676
+ `
6677
+ uniform fp64arithmeticUniforms {
6678
+ uniform float ONE;
6679
+ } fp64;
6677
6680
 
6678
- out vec4 picking_vRGBcolor_Avalid;
6681
+ /*
6682
+ About LUMA_FP64_CODE_ELIMINATION_WORKAROUND
6679
6683
 
6680
- // Normalize unsigned byte color to 0-1 range
6681
- vec3 picking_normalizeColor(vec3 color) {
6682
- return picking.useFloatColors > 0.5 ? color : color / 255.0;
6684
+ The purpose of this workaround is to prevent shader compilers from
6685
+ optimizing away necessary arithmetic operations by swapping their sequences
6686
+ or transform the equation to some 'equivalent' form.
6687
+
6688
+ The method is to multiply an artifical variable, ONE, which will be known to
6689
+ the compiler to be 1 only at runtime. The whole expression is then represented
6690
+ as a polynomial with respective to ONE. In the coefficients of all terms, only one a
6691
+ and one b should appear
6692
+
6693
+ err = (a + b) * ONE^6 - a * ONE^5 - (a + b) * ONE^4 + a * ONE^3 - b - (a + b) * ONE^2 + a * ONE
6694
+ */
6695
+
6696
+ // Divide float number to high and low floats to extend fraction bits
6697
+ vec2 split(float a) {
6698
+ const float SPLIT = 4097.0;
6699
+ float t = a * SPLIT;
6700
+ #if defined(LUMA_FP64_CODE_ELIMINATION_WORKAROUND)
6701
+ float a_hi = t * fp64.ONE - (t - a);
6702
+ float a_lo = a * fp64.ONE - a_hi;
6703
+ #else
6704
+ float a_hi = t - (t - a);
6705
+ float a_lo = a - a_hi;
6706
+ #endif
6707
+ return vec2(a_hi, a_lo);
6683
6708
  }
6684
6709
 
6685
- // Normalize unsigned byte color to 0-1 range
6686
- vec4 picking_normalizeColor(vec4 color) {
6687
- return picking.useFloatColors > 0.5 ? color : color / 255.0;
6710
+ // Divide float number again when high float uses too many fraction bits
6711
+ vec2 split2(vec2 a) {
6712
+ vec2 b = split(a.x);
6713
+ b.y += a.y;
6714
+ return b;
6688
6715
  }
6689
6716
 
6690
- bool picking_isColorZero(vec3 color) {
6691
- return dot(color, vec3(1.0)) < 0.00001;
6717
+ // Special sum operation when a > b
6718
+ vec2 quickTwoSum(float a, float b) {
6719
+ #if defined(LUMA_FP64_CODE_ELIMINATION_WORKAROUND)
6720
+ float sum = (a + b) * fp64.ONE;
6721
+ float err = b - (sum - a) * fp64.ONE;
6722
+ #else
6723
+ float sum = a + b;
6724
+ float err = b - (sum - a);
6725
+ #endif
6726
+ return vec2(sum, err);
6692
6727
  }
6693
6728
 
6694
- bool picking_isColorValid(vec3 color) {
6695
- return dot(color, vec3(1.0)) > 0.00001;
6729
+ // General sum operation
6730
+ vec2 twoSum(float a, float b) {
6731
+ float s = (a + b);
6732
+ #if defined(LUMA_FP64_CODE_ELIMINATION_WORKAROUND)
6733
+ float v = (s * fp64.ONE - a) * fp64.ONE;
6734
+ float err = (a - (s - v) * fp64.ONE) * fp64.ONE * fp64.ONE * fp64.ONE + (b - v);
6735
+ #else
6736
+ float v = s - a;
6737
+ float err = (a - (s - v)) + (b - v);
6738
+ #endif
6739
+ return vec2(s, err);
6696
6740
  }
6697
6741
 
6698
- // Check if this vertex is highlighted
6699
- bool isVertexHighlighted(vec3 vertexColor) {
6700
- vec3 highlightedObjectColor = picking_normalizeColor(picking.highlightedObjectColor);
6701
- return
6702
- bool(picking.isHighlightActive) && picking_isColorZero(abs(vertexColor - highlightedObjectColor));
6742
+ vec2 twoSub(float a, float b) {
6743
+ float s = (a - b);
6744
+ #if defined(LUMA_FP64_CODE_ELIMINATION_WORKAROUND)
6745
+ float v = (s * fp64.ONE - a) * fp64.ONE;
6746
+ float err = (a - (s - v) * fp64.ONE) * fp64.ONE * fp64.ONE * fp64.ONE - (b + v);
6747
+ #else
6748
+ float v = s - a;
6749
+ float err = (a - (s - v)) - (b + v);
6750
+ #endif
6751
+ return vec2(s, err);
6703
6752
  }
6704
6753
 
6705
- // Set the current picking color
6706
- void picking_setPickingColor(vec3 pickingColor) {
6707
- pickingColor = picking_normalizeColor(pickingColor);
6754
+ vec2 twoSqr(float a) {
6755
+ float prod = a * a;
6756
+ vec2 a_fp64 = split(a);
6757
+ #if defined(LUMA_FP64_CODE_ELIMINATION_WORKAROUND)
6758
+ float err = ((a_fp64.x * a_fp64.x - prod) * fp64.ONE + 2.0 * a_fp64.x *
6759
+ a_fp64.y * fp64.ONE * fp64.ONE) + a_fp64.y * a_fp64.y * fp64.ONE * fp64.ONE * fp64.ONE;
6760
+ #else
6761
+ float err = ((a_fp64.x * a_fp64.x - prod) + 2.0 * a_fp64.x * a_fp64.y) + a_fp64.y * a_fp64.y;
6762
+ #endif
6763
+ return vec2(prod, err);
6764
+ }
6708
6765
 
6709
- if (bool(picking.isActive)) {
6710
- // Use alpha as the validity flag. If pickingColor is [0, 0, 0] fragment is non-pickable
6711
- picking_vRGBcolor_Avalid.a = float(picking_isColorValid(pickingColor));
6766
+ vec2 twoProd(float a, float b) {
6767
+ float prod = a * b;
6768
+ vec2 a_fp64 = split(a);
6769
+ vec2 b_fp64 = split(b);
6770
+ float err = ((a_fp64.x * b_fp64.x - prod) + a_fp64.x * b_fp64.y +
6771
+ a_fp64.y * b_fp64.x) + a_fp64.y * b_fp64.y;
6772
+ return vec2(prod, err);
6773
+ }
6712
6774
 
6713
- if (!bool(picking.isAttribute)) {
6714
- // Stores the picking color so that the fragment shader can render it during picking
6715
- picking_vRGBcolor_Avalid.rgb = pickingColor;
6716
- }
6717
- } else {
6718
- // Do the comparison with selected item color in vertex shader as it should mean fewer compares
6719
- picking_vRGBcolor_Avalid.a = float(isVertexHighlighted(pickingColor));
6720
- }
6775
+ vec2 sum_fp64(vec2 a, vec2 b) {
6776
+ vec2 s, t;
6777
+ s = twoSum(a.x, b.x);
6778
+ t = twoSum(a.y, b.y);
6779
+ s.y += t.x;
6780
+ s = quickTwoSum(s.x, s.y);
6781
+ s.y += t.y;
6782
+ s = quickTwoSum(s.x, s.y);
6783
+ return s;
6721
6784
  }
6722
6785
 
6723
- void picking_setPickingAttribute(float value) {
6724
- if (bool(picking.isAttribute)) {
6725
- picking_vRGBcolor_Avalid.r = value;
6726
- }
6786
+ vec2 sub_fp64(vec2 a, vec2 b) {
6787
+ vec2 s, t;
6788
+ s = twoSub(a.x, b.x);
6789
+ t = twoSub(a.y, b.y);
6790
+ s.y += t.x;
6791
+ s = quickTwoSum(s.x, s.y);
6792
+ s.y += t.y;
6793
+ s = quickTwoSum(s.x, s.y);
6794
+ return s;
6727
6795
  }
6728
6796
 
6729
- void picking_setPickingAttribute(vec2 value) {
6730
- if (bool(picking.isAttribute)) {
6731
- picking_vRGBcolor_Avalid.rg = value;
6732
- }
6797
+ vec2 mul_fp64(vec2 a, vec2 b) {
6798
+ vec2 prod = twoProd(a.x, b.x);
6799
+ // y component is for the error
6800
+ prod.y += a.x * b.y;
6801
+ #if defined(LUMA_FP64_HIGH_BITS_OVERFLOW_WORKAROUND)
6802
+ prod = split2(prod);
6803
+ #endif
6804
+ prod = quickTwoSum(prod.x, prod.y);
6805
+ prod.y += a.y * b.x;
6806
+ #if defined(LUMA_FP64_HIGH_BITS_OVERFLOW_WORKAROUND)
6807
+ prod = split2(prod);
6808
+ #endif
6809
+ prod = quickTwoSum(prod.x, prod.y);
6810
+ return prod;
6733
6811
  }
6734
6812
 
6735
- void picking_setPickingAttribute(vec3 value) {
6736
- if (bool(picking.isAttribute)) {
6737
- picking_vRGBcolor_Avalid.rgb = value;
6738
- }
6813
+ vec2 div_fp64(vec2 a, vec2 b) {
6814
+ float xn = 1.0 / b.x;
6815
+ #if defined(LUMA_FP64_HIGH_BITS_OVERFLOW_WORKAROUND)
6816
+ vec2 yn = mul_fp64(a, vec2(xn, 0));
6817
+ #else
6818
+ vec2 yn = a * xn;
6819
+ #endif
6820
+ float diff = (sub_fp64(a, mul_fp64(b, yn))).x;
6821
+ vec2 prod = twoProd(xn, diff);
6822
+ return sum_fp64(yn, prod);
6823
+ }
6824
+
6825
+ vec2 sqrt_fp64(vec2 a) {
6826
+ if (a.x == 0.0 && a.y == 0.0) return vec2(0.0, 0.0);
6827
+ if (a.x < 0.0) return vec2(0.0 / 0.0, 0.0 / 0.0);
6828
+
6829
+ float x = 1.0 / sqrt(a.x);
6830
+ float yn = a.x * x;
6831
+ #if defined(LUMA_FP64_CODE_ELIMINATION_WORKAROUND)
6832
+ vec2 yn_sqr = twoSqr(yn) * fp64.ONE;
6833
+ #else
6834
+ vec2 yn_sqr = twoSqr(yn);
6835
+ #endif
6836
+ float diff = sub_fp64(a, yn_sqr).x;
6837
+ vec2 prod = twoProd(x * 0.5, diff);
6838
+ #if defined(LUMA_FP64_HIGH_BITS_OVERFLOW_WORKAROUND)
6839
+ return sum_fp64(split(yn), prod);
6840
+ #else
6841
+ return sum_fp64(vec2(yn, 0.0), prod);
6842
+ #endif
6739
6843
  }
6740
6844
  `
6741
6845
  );
6742
- var fs2 = (
6743
- /* glsl */
6744
- `uniform pickingUniforms {
6745
- float isActive;
6746
- float isAttribute;
6747
- float isHighlightActive;
6748
- float useFloatColors;
6749
- vec3 highlightedObjectColor;
6750
- vec4 highlightColor;
6751
- } picking;
6752
6846
 
6753
- in vec4 picking_vRGBcolor_Avalid;
6847
+ // src/modules/math/fp64/fp64-functions-glsl.ts
6848
+ var fp64functionShader = (
6849
+ /* glsl */
6850
+ `const vec2 E_FP64 = vec2(2.7182817459106445e+00, 8.254840366817007e-08);
6851
+ const vec2 LOG2_FP64 = vec2(0.6931471824645996e+00, -1.9046542121259336e-09);
6852
+ const vec2 PI_FP64 = vec2(3.1415927410125732, -8.742278012618954e-8);
6853
+ const vec2 TWO_PI_FP64 = vec2(6.2831854820251465, -1.7484556025237907e-7);
6854
+ const vec2 PI_2_FP64 = vec2(1.5707963705062866, -4.371139006309477e-8);
6855
+ const vec2 PI_4_FP64 = vec2(0.7853981852531433, -2.1855695031547384e-8);
6856
+ const vec2 PI_16_FP64 = vec2(0.19634954631328583, -5.463923757886846e-9);
6857
+ const vec2 PI_16_2_FP64 = vec2(0.39269909262657166, -1.0927847515773692e-8);
6858
+ const vec2 PI_16_3_FP64 = vec2(0.5890486240386963, -1.4906100798128818e-9);
6859
+ const vec2 PI_180_FP64 = vec2(0.01745329238474369, 1.3519960498364902e-10);
6754
6860
 
6755
- /*
6756
- * Returns highlight color if this item is selected.
6757
- */
6758
- vec4 picking_filterHighlightColor(vec4 color) {
6759
- // If we are still picking, we don't highlight
6760
- if (picking.isActive > 0.5) {
6761
- return color;
6762
- }
6861
+ const vec2 SIN_TABLE_0_FP64 = vec2(0.19509032368659973, -1.6704714833615242e-9);
6862
+ const vec2 SIN_TABLE_1_FP64 = vec2(0.3826834261417389, 6.22335089017767e-9);
6863
+ const vec2 SIN_TABLE_2_FP64 = vec2(0.5555702447891235, -1.1769521357507529e-8);
6864
+ const vec2 SIN_TABLE_3_FP64 = vec2(0.7071067690849304, 1.2101617041793133e-8);
6763
6865
 
6764
- bool selected = bool(picking_vRGBcolor_Avalid.a);
6866
+ const vec2 COS_TABLE_0_FP64 = vec2(0.9807852506637573, 2.9739473106360492e-8);
6867
+ const vec2 COS_TABLE_1_FP64 = vec2(0.9238795042037964, 2.8307490351764386e-8);
6868
+ const vec2 COS_TABLE_2_FP64 = vec2(0.8314695954322815, 1.6870263741530778e-8);
6869
+ const vec2 COS_TABLE_3_FP64 = vec2(0.7071067690849304, 1.2101617152815436e-8);
6765
6870
 
6766
- if (selected) {
6767
- // Blend in highlight color based on its alpha value
6768
- float highLightAlpha = picking.highlightColor.a;
6769
- float blendedAlpha = highLightAlpha + color.a * (1.0 - highLightAlpha);
6770
- float highLightRatio = highLightAlpha / blendedAlpha;
6871
+ const vec2 INVERSE_FACTORIAL_3_FP64 = vec2(1.666666716337204e-01, -4.967053879312289e-09); // 1/3!
6872
+ const vec2 INVERSE_FACTORIAL_4_FP64 = vec2(4.16666679084301e-02, -1.2417634698280722e-09); // 1/4!
6873
+ const vec2 INVERSE_FACTORIAL_5_FP64 = vec2(8.333333767950535e-03, -4.34617203337595e-10); // 1/5!
6874
+ const vec2 INVERSE_FACTORIAL_6_FP64 = vec2(1.3888889225199819e-03, -3.3631094437103215e-11); // 1/6!
6875
+ const vec2 INVERSE_FACTORIAL_7_FP64 = vec2(1.9841270113829523e-04, -2.725596874933456e-12); // 1/7!
6876
+ const vec2 INVERSE_FACTORIAL_8_FP64 = vec2(2.4801587642286904e-05, -3.406996025904184e-13); // 1/8!
6877
+ const vec2 INVERSE_FACTORIAL_9_FP64 = vec2(2.75573188446287533e-06, 3.7935713937038186e-14); // 1/9!
6878
+ const vec2 INVERSE_FACTORIAL_10_FP64 = vec2(2.755731998149713e-07, -7.575112367869873e-15); // 1/10!
6771
6879
 
6772
- vec3 blendedRGB = mix(color.rgb, picking.highlightColor.rgb, highLightRatio);
6773
- return vec4(blendedRGB, blendedAlpha);
6774
- } else {
6775
- return color;
6776
- }
6880
+ float nint(float d) {
6881
+ if (d == floor(d)) return d;
6882
+ return floor(d + 0.5);
6777
6883
  }
6778
6884
 
6779
- /*
6780
- * Returns picking color if picking enabled else unmodified argument.
6781
- */
6782
- vec4 picking_filterPickingColor(vec4 color) {
6783
- if (bool(picking.isActive)) {
6784
- if (picking_vRGBcolor_Avalid.a == 0.0) {
6785
- discard;
6885
+ vec2 nint_fp64(vec2 a) {
6886
+ float hi = nint(a.x);
6887
+ float lo;
6888
+ vec2 tmp;
6889
+ if (hi == a.x) {
6890
+ lo = nint(a.y);
6891
+ tmp = quickTwoSum(hi, lo);
6892
+ } else {
6893
+ lo = 0.0;
6894
+ if (abs(hi - a.x) == 0.5 && a.y < 0.0) {
6895
+ hi -= 1.0;
6896
+ }
6897
+ tmp = vec2(hi, lo);
6786
6898
  }
6787
- return picking_vRGBcolor_Avalid;
6788
- }
6789
- return color;
6899
+ return tmp;
6790
6900
  }
6791
6901
 
6792
- /*
6793
- * Returns picking color if picking is enabled if not
6794
- * highlight color if this item is selected, otherwise unmodified argument.
6795
- */
6796
- vec4 picking_filterColor(vec4 color) {
6797
- vec4 highlightColor = picking_filterHighlightColor(color);
6798
- return picking_filterPickingColor(highlightColor);
6799
- }
6800
- `
6801
- );
6802
- var picking = {
6803
- props: {},
6804
- uniforms: {},
6805
- name: "picking",
6806
- uniformTypes: {
6807
- isActive: "f32",
6808
- isAttribute: "f32",
6809
- isHighlightActive: "f32",
6810
- useFloatColors: "f32",
6811
- highlightedObjectColor: "vec3<f32>",
6812
- highlightColor: "vec4<f32>"
6813
- },
6814
- defaultUniforms: {
6815
- isActive: false,
6816
- isAttribute: false,
6817
- isHighlightActive: false,
6818
- useFloatColors: true,
6819
- highlightedObjectColor: [0, 0, 0],
6820
- highlightColor: DEFAULT_HIGHLIGHT_COLOR
6821
- },
6822
- vs,
6823
- fs: fs2,
6824
- getUniforms
6825
- };
6826
- function getUniforms(opts = {}, prevUniforms) {
6827
- const uniforms = {};
6828
- if (opts.highlightedObjectColor === void 0) {
6829
- } else if (opts.highlightedObjectColor === null) {
6830
- uniforms.isHighlightActive = false;
6831
- } else {
6832
- uniforms.isHighlightActive = true;
6833
- const highlightedObjectColor = opts.highlightedObjectColor.slice(0, 3);
6834
- uniforms.highlightedObjectColor = highlightedObjectColor;
6835
- }
6836
- if (opts.highlightColor) {
6837
- const color = Array.from(opts.highlightColor, (x) => x / 255);
6838
- if (!Number.isFinite(color[3])) {
6839
- color[3] = 1;
6840
- }
6841
- uniforms.highlightColor = color;
6842
- }
6843
- if (opts.isActive !== void 0) {
6844
- uniforms.isActive = Boolean(opts.isActive);
6845
- uniforms.isAttribute = Boolean(opts.isAttribute);
6846
- }
6847
- if (opts.useFloatColors !== void 0) {
6848
- uniforms.useFloatColors = Boolean(opts.useFloatColors);
6849
- }
6850
- return uniforms;
6851
- }
6902
+ /* k_power controls how much range reduction we would like to have
6903
+ Range reduction uses the following method:
6904
+ assume a = k_power * r + m * log(2), k and m being integers.
6905
+ Set k_power = 4 (we can choose other k to trade accuracy with performance.
6906
+ we only need to calculate exp(r) and using exp(a) = 2^m * exp(r)^k_power;
6907
+ */
6852
6908
 
6853
- // src/modules/lighting/lights/lighting.ts
6854
- var import_core3 = __toESM(require_core(), 1);
6909
+ vec2 exp_fp64(vec2 a) {
6910
+ // We need to make sure these two numbers match
6911
+ // as bit-wise shift is not available in GLSL 1.0
6912
+ const int k_power = 4;
6913
+ const float k = 16.0;
6855
6914
 
6856
- // src/modules/lighting/lights/lighting-uniforms-glsl.ts
6857
- var lightingUniformsGLSL = (
6858
- /* glsl */
6859
- `precision highp int;
6915
+ const float inv_k = 1.0 / k;
6860
6916
 
6861
- // #if (defined(SHADER_TYPE_FRAGMENT) && defined(LIGHTING_FRAGMENT)) || (defined(SHADER_TYPE_VERTEX) && defined(LIGHTING_VERTEX))
6862
- struct AmbientLight {
6863
- vec3 color;
6864
- };
6917
+ if (a.x <= -88.0) return vec2(0.0, 0.0);
6918
+ if (a.x >= 88.0) return vec2(1.0 / 0.0, 1.0 / 0.0);
6919
+ if (a.x == 0.0 && a.y == 0.0) return vec2(1.0, 0.0);
6920
+ if (a.x == 1.0 && a.y == 0.0) return E_FP64;
6865
6921
 
6866
- struct PointLight {
6867
- vec3 color;
6868
- vec3 position;
6869
- vec3 attenuation; // 2nd order x:Constant-y:Linear-z:Exponential
6870
- };
6922
+ float m = floor(a.x / LOG2_FP64.x + 0.5);
6923
+ vec2 r = sub_fp64(a, mul_fp64(LOG2_FP64, vec2(m, 0.0))) * inv_k;
6924
+ vec2 s, t, p;
6871
6925
 
6872
- struct DirectionalLight {
6873
- vec3 color;
6874
- vec3 direction;
6875
- };
6926
+ p = mul_fp64(r, r);
6927
+ s = sum_fp64(r, p * 0.5);
6928
+ p = mul_fp64(p, r);
6929
+ t = mul_fp64(p, INVERSE_FACTORIAL_3_FP64);
6876
6930
 
6877
- uniform lightingUniforms {
6878
- int enabled;
6879
- int lightType;
6931
+ s = sum_fp64(s, t);
6932
+ p = mul_fp64(p, r);
6933
+ t = mul_fp64(p, INVERSE_FACTORIAL_4_FP64);
6880
6934
 
6881
- int directionalLightCount;
6882
- int pointLightCount;
6935
+ s = sum_fp64(s, t);
6936
+ p = mul_fp64(p, r);
6937
+ t = mul_fp64(p, INVERSE_FACTORIAL_5_FP64);
6883
6938
 
6884
- vec3 ambientColor;
6939
+ // s = sum_fp64(s, t);
6940
+ // p = mul_fp64(p, r);
6941
+ // t = mul_fp64(p, INVERSE_FACTORIAL_6_FP64);
6885
6942
 
6886
- vec3 lightColor0;
6887
- vec3 lightPosition0;
6888
- vec3 lightDirection0;
6889
- vec3 lightAttenuation0;
6943
+ // s = sum_fp64(s, t);
6944
+ // p = mul_fp64(p, r);
6945
+ // t = mul_fp64(p, INVERSE_FACTORIAL_7_FP64);
6890
6946
 
6891
- vec3 lightColor1;
6892
- vec3 lightPosition1;
6893
- vec3 lightDirection1;
6894
- vec3 lightAttenuation1;
6947
+ s = sum_fp64(s, t);
6895
6948
 
6896
- vec3 lightColor2;
6897
- vec3 lightPosition2;
6898
- vec3 lightDirection2;
6899
- vec3 lightAttenuation2;
6900
- } lighting;
6901
6949
 
6902
- PointLight lighting_getPointLight(int index) {
6903
- switch (index) {
6904
- case 0:
6905
- return PointLight(lighting.lightColor0, lighting.lightPosition0, lighting.lightAttenuation0);
6906
- case 1:
6907
- return PointLight(lighting.lightColor1, lighting.lightPosition1, lighting.lightAttenuation1);
6908
- case 2:
6909
- default:
6910
- return PointLight(lighting.lightColor2, lighting.lightPosition2, lighting.lightAttenuation2);
6950
+ // At this point, s = exp(r) - 1; but after following 4 recursions, we will get exp(r) ^ 512 - 1.
6951
+ for (int i = 0; i < k_power; i++) {
6952
+ s = sum_fp64(s * 2.0, mul_fp64(s, s));
6911
6953
  }
6912
- }
6913
6954
 
6914
- DirectionalLight lighting_getDirectionalLight(int index) {
6915
- switch (index) {
6916
- case 0:
6917
- return DirectionalLight(lighting.lightColor0, lighting.lightDirection0);
6918
- case 1:
6919
- return DirectionalLight(lighting.lightColor1, lighting.lightDirection1);
6920
- case 2:
6921
- default:
6922
- return DirectionalLight(lighting.lightColor2, lighting.lightDirection2);
6923
- }
6924
- }
6955
+ #if defined(NVIDIA_FP64_WORKAROUND) || defined(INTEL_FP64_WORKAROUND)
6956
+ s = sum_fp64(s, vec2(fp64.ONE, 0.0));
6957
+ #else
6958
+ s = sum_fp64(s, vec2(1.0, 0.0));
6959
+ #endif
6925
6960
 
6926
- float getPointLightAttenuation(PointLight pointLight, float distance) {
6927
- return pointLight.attenuation.x
6928
- + pointLight.attenuation.y * distance
6929
- + pointLight.attenuation.z * distance * distance;
6961
+ return s * pow(2.0, m);
6962
+ // return r;
6930
6963
  }
6931
6964
 
6932
- // #endif
6933
- `
6934
- );
6965
+ vec2 log_fp64(vec2 a)
6966
+ {
6967
+ if (a.x == 1.0 && a.y == 0.0) return vec2(0.0, 0.0);
6968
+ if (a.x <= 0.0) return vec2(0.0 / 0.0, 0.0 / 0.0);
6969
+ vec2 x = vec2(log(a.x), 0.0);
6970
+ vec2 s;
6971
+ #if defined(NVIDIA_FP64_WORKAROUND) || defined(INTEL_FP64_WORKAROUND)
6972
+ s = vec2(fp64.ONE, 0.0);
6973
+ #else
6974
+ s = vec2(1.0, 0.0);
6975
+ #endif
6935
6976
 
6936
- // src/modules/lighting/lights/lighting-uniforms-wgsl.ts
6937
- var lightingUniformsWGSL = (
6938
- /* wgsl */
6939
- `// #if (defined(SHADER_TYPE_FRAGMENT) && defined(LIGHTING_FRAGMENT)) || (defined(SHADER_TYPE_VERTEX) && defined(LIGHTING_VERTEX))
6940
- struct AmbientLight {
6941
- color: vec3<f32>,
6942
- };
6977
+ x = sub_fp64(sum_fp64(x, mul_fp64(a, exp_fp64(-x))), s);
6978
+ return x;
6979
+ }
6943
6980
 
6944
- struct PointLight {
6945
- color: vec3<f32>,
6946
- position: vec3<f32>,
6947
- attenuation: vec3<f32>, // 2nd order x:Constant-y:Linear-z:Exponential
6948
- };
6981
+ vec2 sin_taylor_fp64(vec2 a) {
6982
+ vec2 r, s, t, x;
6949
6983
 
6950
- struct DirectionalLight {
6951
- color: vec3<f32>,
6952
- direction: vec3<f32>,
6953
- };
6984
+ if (a.x == 0.0 && a.y == 0.0) {
6985
+ return vec2(0.0, 0.0);
6986
+ }
6954
6987
 
6955
- struct lightingUniforms {
6956
- enabled: i32,
6957
- poightCount: i32,
6958
- directionalLightCount: i32,
6988
+ x = -mul_fp64(a, a);
6989
+ s = a;
6990
+ r = a;
6959
6991
 
6960
- ambientColor: vec3<f32>,
6992
+ r = mul_fp64(r, x);
6993
+ t = mul_fp64(r, INVERSE_FACTORIAL_3_FP64);
6994
+ s = sum_fp64(s, t);
6961
6995
 
6962
- // TODO - support multiple lights by uncommenting arrays below
6963
- lightType: i32,
6964
- lightColor: vec3<f32>,
6965
- lightDirection: vec3<f32>,
6966
- lightPosition: vec3<f32>,
6967
- lightAttenuation: vec3<f32>,
6996
+ r = mul_fp64(r, x);
6997
+ t = mul_fp64(r, INVERSE_FACTORIAL_5_FP64);
6998
+ s = sum_fp64(s, t);
6968
6999
 
6969
- // AmbientLight ambientLight;
6970
- // PointLight pointLight[MAX_LIGHTS];
6971
- // DirectionalLight directionalLight[MAX_LIGHTS];
6972
- };
7000
+ /* keep the following commented code in case we need them
7001
+ for extra accuracy from the Taylor expansion*/
6973
7002
 
6974
- // Binding 0:1 is reserved for lighting (Note: could go into separate bind group as it is stable across draw calls)
6975
- @binding(1) @group(0) var<uniform> lighting : lightingUniforms;
7003
+ // r = mul_fp64(r, x);
7004
+ // t = mul_fp64(r, INVERSE_FACTORIAL_7_FP64);
7005
+ // s = sum_fp64(s, t);
6976
7006
 
6977
- fn lighting_getPointLight(index: i32) -> PointLight {
6978
- return PointLight(lighting.lightColor, lighting.lightPosition, lighting.lightAttenuation);
6979
- }
6980
-
6981
- fn lighting_getDirectionalLight(index: i32) -> DirectionalLight {
6982
- return DirectionalLight(lighting.lightColor, lighting.lightDirection);
6983
- }
7007
+ // r = mul_fp64(r, x);
7008
+ // t = mul_fp64(r, INVERSE_FACTORIAL_9_FP64);
7009
+ // s = sum_fp64(s, t);
6984
7010
 
6985
- fn getPointLightAttenuation(pointLight: PointLight, distance: f32) -> f32 {
6986
- return pointLight.attenuation.x
6987
- + pointLight.attenuation.y * distance
6988
- + pointLight.attenuation.z * distance * distance;
7011
+ return s;
6989
7012
  }
6990
- `
6991
- );
6992
7013
 
6993
- // src/modules/lighting/lights/lighting.ts
6994
- var MAX_LIGHTS = 3;
6995
- var COLOR_FACTOR = 255;
6996
- var lighting = {
6997
- props: {},
6998
- uniforms: {},
6999
- name: "lighting",
7000
- defines: {
7001
- MAX_LIGHTS
7002
- },
7003
- uniformTypes: {
7004
- enabled: "i32",
7005
- lightType: "i32",
7006
- directionalLightCount: "i32",
7007
- pointLightCount: "i32",
7008
- ambientLightColor: "vec3<f32>",
7009
- // TODO define as arrays once we have appropriate uniformTypes
7010
- lightColor0: "vec3<f32>",
7011
- lightPosition0: "vec3<f32>",
7012
- // TODO - could combine direction and attenuation
7013
- lightDirection0: "vec3<f32>",
7014
- lightAttenuation0: "vec3<f32>",
7015
- lightColor1: "vec3<f32>",
7016
- lightPosition1: "vec3<f32>",
7017
- lightDirection1: "vec3<f32>",
7018
- lightAttenuation1: "vec3<f32>",
7019
- lightColor2: "vec3<f32>",
7020
- lightPosition2: "vec3<f32>",
7021
- lightDirection2: "vec3<f32>",
7022
- lightAttenuation2: "vec3<f32>"
7023
- },
7024
- defaultUniforms: {
7025
- enabled: 1,
7026
- lightType: 0 /* POINT */,
7027
- directionalLightCount: 0,
7028
- pointLightCount: 0,
7029
- ambientLightColor: [0.1, 0.1, 0.1],
7030
- lightColor0: [1, 1, 1],
7031
- lightPosition0: [1, 1, 2],
7032
- // TODO - could combine direction and attenuation
7033
- lightDirection0: [1, 1, 1],
7034
- lightAttenuation0: [1, 0, 0],
7035
- lightColor1: [1, 1, 1],
7036
- lightPosition1: [1, 1, 2],
7037
- lightDirection1: [1, 1, 1],
7038
- lightAttenuation1: [1, 0, 0],
7039
- lightColor2: [1, 1, 1],
7040
- lightPosition2: [1, 1, 2],
7041
- lightDirection2: [1, 1, 1],
7042
- lightAttenuation2: [1, 0, 0]
7043
- },
7044
- source: lightingUniformsWGSL,
7045
- vs: lightingUniformsGLSL,
7046
- fs: lightingUniformsGLSL,
7047
- getUniforms: getUniforms2
7048
- };
7049
- function getUniforms2(props, prevUniforms = {}) {
7050
- props = props ? { ...props } : props;
7051
- if (!props) {
7052
- return { ...lighting.defaultUniforms };
7053
- }
7054
- if (props.lights) {
7055
- props = { ...props, ...extractLightTypes(props.lights), lights: void 0 };
7056
- }
7057
- const { ambientLight, pointLights, directionalLights } = props || {};
7058
- const hasLights = ambientLight || pointLights && pointLights.length > 0 || directionalLights && directionalLights.length > 0;
7059
- if (!hasLights) {
7060
- return { ...lighting.defaultUniforms, enabled: 0 };
7061
- }
7062
- const uniforms = {
7063
- ...lighting.defaultUniforms,
7064
- ...prevUniforms,
7065
- ...getLightSourceUniforms({ ambientLight, pointLights, directionalLights })
7066
- };
7067
- if (props.enabled !== void 0) {
7068
- uniforms.enabled = props.enabled ? 1 : 0;
7069
- }
7070
- return uniforms;
7071
- }
7072
- function getLightSourceUniforms({
7073
- ambientLight,
7074
- pointLights = [],
7075
- directionalLights = []
7076
- }) {
7077
- const lightSourceUniforms = {};
7078
- lightSourceUniforms.ambientLightColor = convertColor(ambientLight);
7079
- let currentLight = 0;
7080
- for (const pointLight of pointLights) {
7081
- lightSourceUniforms.lightType = 0 /* POINT */;
7082
- const i = currentLight;
7083
- lightSourceUniforms[`lightColor${i}`] = convertColor(pointLight);
7084
- lightSourceUniforms[`lightPosition${i}`] = pointLight.position;
7085
- lightSourceUniforms[`lightAttenuation${i}`] = pointLight.attenuation || [1, 0, 0];
7086
- currentLight++;
7087
- }
7088
- for (const directionalLight of directionalLights) {
7089
- lightSourceUniforms.lightType = 1 /* DIRECTIONAL */;
7090
- const i = currentLight;
7091
- lightSourceUniforms[`lightColor${i}`] = convertColor(directionalLight);
7092
- lightSourceUniforms[`lightDirection${i}`] = directionalLight.direction;
7093
- currentLight++;
7094
- }
7095
- if (currentLight > MAX_LIGHTS) {
7096
- import_core3.log.warn("MAX_LIGHTS exceeded")();
7097
- }
7098
- lightSourceUniforms.directionalLightCount = directionalLights.length;
7099
- lightSourceUniforms.pointLightCount = pointLights.length;
7100
- return lightSourceUniforms;
7101
- }
7102
- function extractLightTypes(lights2) {
7103
- const lightSources = { pointLights: [], directionalLights: [] };
7104
- for (const light of lights2 || []) {
7105
- switch (light.type) {
7106
- case "ambient":
7107
- lightSources.ambientLight = light;
7108
- break;
7109
- case "directional":
7110
- lightSources.directionalLights?.push(light);
7111
- break;
7112
- case "point":
7113
- lightSources.pointLights?.push(light);
7114
- break;
7115
- default:
7116
- }
7117
- }
7118
- return lightSources;
7119
- }
7120
- function convertColor(colorDef = {}) {
7121
- const { color = [0, 0, 0], intensity = 1 } = colorDef;
7122
- return color.map((component) => component * intensity / COLOR_FACTOR);
7014
+ vec2 cos_taylor_fp64(vec2 a) {
7015
+ vec2 r, s, t, x;
7016
+
7017
+ if (a.x == 0.0 && a.y == 0.0) {
7018
+ return vec2(1.0, 0.0);
7123
7019
  }
7124
7020
 
7125
- // src/modules/lighting/no-material/dirlight.ts
7126
- var SOURCE_WGSL = (
7127
- /* WGSL */
7128
- `
7129
- struct dirlightUniforms {
7130
- lightDirection: vec3<f32>,
7131
- };
7021
+ x = -mul_fp64(a, a);
7022
+ r = x;
7023
+ s = sum_fp64(vec2(1.0, 0.0), r * 0.5);
7132
7024
 
7133
- alias DirlightNormal = vec3<f32>;
7025
+ r = mul_fp64(r, x);
7026
+ t = mul_fp64(r, INVERSE_FACTORIAL_4_FP64);
7027
+ s = sum_fp64(s, t);
7134
7028
 
7135
- struct DirlightInputs {
7136
- normal: DirlightNormal,
7137
- };
7029
+ r = mul_fp64(r, x);
7030
+ t = mul_fp64(r, INVERSE_FACTORIAL_6_FP64);
7031
+ s = sum_fp64(s, t);
7138
7032
 
7139
- @binding(1) @group(0) var<uniform> dirlight : dirlightUniforms;
7033
+ /* keep the following commented code in case we need them
7034
+ for extra accuracy from the Taylor expansion*/
7140
7035
 
7141
- // For vertex
7142
- fn dirlight_setNormal(normal: vec3<f32>) -> DirlightNormal {
7143
- return normalize(normal);
7144
- }
7036
+ // r = mul_fp64(r, x);
7037
+ // t = mul_fp64(r, INVERSE_FACTORIAL_8_FP64);
7038
+ // s = sum_fp64(s, t);
7145
7039
 
7146
- // Returns color attenuated by angle from light source
7147
- fn dirlight_filterColor(color: vec4<f32>, inputs: DirlightInputs) -> vec4<f32> {
7148
- // TODO - fix default light direction
7149
- // let lightDirection = dirlight.lightDirection;
7150
- let lightDirection = vec3<f32>(1, 1, 1);
7151
- let d: f32 = abs(dot(inputs.normal, normalize(lightDirection)));
7152
- return vec4<f32>(color.rgb * d, color.a);
7153
- }
7154
- `
7155
- );
7156
- var VS_GLSL = (
7157
- /* glsl */
7158
- `out vec3 dirlight_vNormal;
7040
+ // r = mul_fp64(r, x);
7041
+ // t = mul_fp64(r, INVERSE_FACTORIAL_10_FP64);
7042
+ // s = sum_fp64(s, t);
7159
7043
 
7160
- void dirlight_setNormal(vec3 normal) {
7161
- dirlight_vNormal = normalize(normal);
7044
+ return s;
7162
7045
  }
7163
- `
7164
- );
7165
- var FS_GLSL = (
7166
- /* glsl */
7167
- `uniform dirlightUniforms {
7168
- vec3 lightDirection;
7169
- } dirlight;
7170
7046
 
7171
- in vec3 dirlight_vNormal;
7047
+ void sincos_taylor_fp64(vec2 a, out vec2 sin_t, out vec2 cos_t) {
7048
+ if (a.x == 0.0 && a.y == 0.0) {
7049
+ sin_t = vec2(0.0, 0.0);
7050
+ cos_t = vec2(1.0, 0.0);
7051
+ }
7172
7052
 
7173
- // Returns color attenuated by angle from light source
7174
- vec4 dirlight_filterColor(vec4 color) {
7175
- float d = abs(dot(dirlight_vNormal, normalize(dirlight.lightDirection)));
7176
- return vec4(color.rgb * d, color.a);
7053
+ sin_t = sin_taylor_fp64(a);
7054
+ cos_t = sqrt_fp64(sub_fp64(vec2(1.0, 0.0), mul_fp64(sin_t, sin_t)));
7177
7055
  }
7178
- `
7179
- );
7180
- var dirlight = {
7181
- props: {},
7182
- uniforms: {},
7183
- name: "dirlight",
7184
- dependencies: [],
7185
- source: SOURCE_WGSL,
7186
- vs: VS_GLSL,
7187
- fs: FS_GLSL,
7188
- // fragmentInputs: [
7189
- // {
7190
- // name: 'dirlight_vNormal',
7191
- // type: 'vec3<f32>'
7192
- // }
7193
- // ],
7194
- uniformTypes: {
7195
- lightDirection: "vec3<f32>"
7196
- },
7197
- defaultUniforms: {
7198
- lightDirection: [1, 1, 2]
7199
- },
7200
- getUniforms: getUniforms3
7201
- };
7202
- function getUniforms3(opts = dirlight.defaultUniforms) {
7203
- const uniforms = {};
7204
- if (opts.lightDirection) {
7205
- uniforms.dirlight_uLightDirection = opts.lightDirection;
7056
+
7057
+ vec2 sin_fp64(vec2 a) {
7058
+ if (a.x == 0.0 && a.y == 0.0) {
7059
+ return vec2(0.0, 0.0);
7206
7060
  }
7207
- return uniforms;
7208
- }
7209
7061
 
7210
- // src/modules/lighting/phong-material/phong-shaders-glsl.ts
7211
- var PHONG_VS = (
7212
- /* glsl */
7213
- `uniform phongMaterialUniforms {
7214
- uniform float ambient;
7215
- uniform float diffuse;
7216
- uniform float shininess;
7217
- uniform vec3 specularColor;
7218
- } material;
7219
- `
7220
- );
7221
- var PHONG_FS = (
7222
- /* glsl */
7223
- `uniform phongMaterialUniforms {
7224
- uniform float ambient;
7225
- uniform float diffuse;
7226
- uniform float shininess;
7227
- uniform vec3 specularColor;
7228
- } material;
7062
+ // 2pi range reduction
7063
+ vec2 z = nint_fp64(div_fp64(a, TWO_PI_FP64));
7064
+ vec2 r = sub_fp64(a, mul_fp64(TWO_PI_FP64, z));
7229
7065
 
7230
- vec3 lighting_getLightColor(vec3 surfaceColor, vec3 light_direction, vec3 view_direction, vec3 normal_worldspace, vec3 color) {
7231
- vec3 halfway_direction = normalize(light_direction + view_direction);
7232
- float lambertian = dot(light_direction, normal_worldspace);
7233
- float specular = 0.0;
7234
- if (lambertian > 0.0) {
7235
- float specular_angle = max(dot(normal_worldspace, halfway_direction), 0.0);
7236
- specular = pow(specular_angle, material.shininess);
7237
- }
7238
- lambertian = max(lambertian, 0.0);
7239
- return (lambertian * material.diffuse * surfaceColor + specular * material.specularColor) * color;
7240
- }
7066
+ vec2 t;
7067
+ float q = floor(r.x / PI_2_FP64.x + 0.5);
7068
+ int j = int(q);
7241
7069
 
7242
- vec3 lighting_getLightColor(vec3 surfaceColor, vec3 cameraPosition, vec3 position_worldspace, vec3 normal_worldspace) {
7243
- vec3 lightColor = surfaceColor;
7070
+ if (j < -2 || j > 2) {
7071
+ return vec2(0.0 / 0.0, 0.0 / 0.0);
7072
+ }
7244
7073
 
7245
- if (lighting.enabled == 0) {
7246
- return lightColor;
7247
- }
7074
+ t = sub_fp64(r, mul_fp64(PI_2_FP64, vec2(q, 0.0)));
7248
7075
 
7249
- vec3 view_direction = normalize(cameraPosition - position_worldspace);
7250
- lightColor = material.ambient * surfaceColor * lighting.ambientColor;
7076
+ q = floor(t.x / PI_16_FP64.x + 0.5);
7077
+ int k = int(q);
7251
7078
 
7252
- for (int i = 0; i < lighting.pointLightCount; i++) {
7253
- PointLight pointLight = lighting_getPointLight(i);
7254
- vec3 light_position_worldspace = pointLight.position;
7255
- vec3 light_direction = normalize(light_position_worldspace - position_worldspace);
7256
- float light_attenuation = getPointLightAttenuation(pointLight, distance(light_position_worldspace, position_worldspace));
7257
- lightColor += lighting_getLightColor(surfaceColor, light_direction, view_direction, normal_worldspace, pointLight.color / light_attenuation);
7258
- }
7079
+ if (k == 0) {
7080
+ if (j == 0) {
7081
+ return sin_taylor_fp64(t);
7082
+ } else if (j == 1) {
7083
+ return cos_taylor_fp64(t);
7084
+ } else if (j == -1) {
7085
+ return -cos_taylor_fp64(t);
7086
+ } else {
7087
+ return -sin_taylor_fp64(t);
7088
+ }
7089
+ }
7259
7090
 
7260
- int totalLights = min(MAX_LIGHTS, lighting.pointLightCount + lighting.directionalLightCount);
7261
- for (int i = lighting.pointLightCount; i < totalLights; i++) {
7262
- DirectionalLight directionalLight = lighting_getDirectionalLight(i);
7263
- lightColor += lighting_getLightColor(surfaceColor, -directionalLight.direction, view_direction, normal_worldspace, directionalLight.color);
7264
- }
7265
-
7266
- return lightColor;
7267
- }
7268
- `
7269
- );
7091
+ int abs_k = int(abs(float(k)));
7270
7092
 
7271
- // src/modules/lighting/gouraud-material/gouraud-material.ts
7272
- var gouraudMaterial = {
7273
- props: {},
7274
- name: "gouraudMaterial",
7275
- // Note these are switched between phong and gouraud
7276
- vs: PHONG_FS.replace("phongMaterial", "gouraudMaterial"),
7277
- fs: PHONG_VS.replace("phongMaterial", "gouraudMaterial"),
7278
- defines: {
7279
- LIGHTING_VERTEX: 1
7280
- },
7281
- dependencies: [lighting],
7282
- uniformTypes: {
7283
- ambient: "f32",
7284
- diffuse: "f32",
7285
- shininess: "f32",
7286
- specularColor: "vec3<f32>"
7287
- },
7288
- defaultUniforms: {
7289
- ambient: 0.35,
7290
- diffuse: 0.6,
7291
- shininess: 32,
7292
- specularColor: [0.15, 0.15, 0.15]
7293
- },
7294
- getUniforms(props) {
7295
- const uniforms = { ...props };
7296
- if (uniforms.specularColor) {
7297
- uniforms.specularColor = uniforms.specularColor.map((x) => x / 255);
7298
- }
7299
- return { ...gouraudMaterial.defaultUniforms, ...uniforms };
7093
+ if (abs_k > 4) {
7094
+ return vec2(0.0 / 0.0, 0.0 / 0.0);
7095
+ } else {
7096
+ t = sub_fp64(t, mul_fp64(PI_16_FP64, vec2(q, 0.0)));
7300
7097
  }
7301
- };
7302
-
7303
- // src/modules/lighting/phong-material/phong-shaders-wgsl.ts
7304
- var PHONG_WGSL = (
7305
- /* wgsl */
7306
- `struct phongMaterialUniforms {
7307
- ambient: f32,
7308
- diffuse: f32,
7309
- shininess: f32,
7310
- specularColor: vec3<f32>,
7311
- };
7312
7098
 
7313
- @binding(2) @group(0) var<uniform> material : phongMaterialUniforms;
7099
+ vec2 u = vec2(0.0, 0.0);
7100
+ vec2 v = vec2(0.0, 0.0);
7314
7101
 
7315
- fn lighting_getLightColor(surfaceColor: vec3<f32>, light_direction: vec3<f32>, view_direction: vec3<f32>, normal_worldspace: vec3<f32>, color: vec3<f32>) -> vec3<f32> {
7316
- let halfway_direction: vec3<f32> = normalize(light_direction + view_direction);
7317
- var lambertian: f32 = dot(light_direction, normal_worldspace);
7318
- var specular: f32 = 0.0;
7319
- if (lambertian > 0.0) {
7320
- let specular_angle = max(dot(normal_worldspace, halfway_direction), 0.0);
7321
- specular = pow(specular_angle, material.shininess);
7322
- }
7323
- lambertian = max(lambertian, 0.0);
7324
- return (lambertian * material.diffuse * surfaceColor + specular * material.specularColor) * color;
7325
- }
7102
+ #if defined(NVIDIA_FP64_WORKAROUND) || defined(INTEL_FP64_WORKAROUND)
7103
+ if (abs(float(abs_k) - 1.0) < 0.5) {
7104
+ u = COS_TABLE_0_FP64;
7105
+ v = SIN_TABLE_0_FP64;
7106
+ } else if (abs(float(abs_k) - 2.0) < 0.5) {
7107
+ u = COS_TABLE_1_FP64;
7108
+ v = SIN_TABLE_1_FP64;
7109
+ } else if (abs(float(abs_k) - 3.0) < 0.5) {
7110
+ u = COS_TABLE_2_FP64;
7111
+ v = SIN_TABLE_2_FP64;
7112
+ } else if (abs(float(abs_k) - 4.0) < 0.5) {
7113
+ u = COS_TABLE_3_FP64;
7114
+ v = SIN_TABLE_3_FP64;
7115
+ }
7116
+ #else
7117
+ if (abs_k == 1) {
7118
+ u = COS_TABLE_0_FP64;
7119
+ v = SIN_TABLE_0_FP64;
7120
+ } else if (abs_k == 2) {
7121
+ u = COS_TABLE_1_FP64;
7122
+ v = SIN_TABLE_1_FP64;
7123
+ } else if (abs_k == 3) {
7124
+ u = COS_TABLE_2_FP64;
7125
+ v = SIN_TABLE_2_FP64;
7126
+ } else if (abs_k == 4) {
7127
+ u = COS_TABLE_3_FP64;
7128
+ v = SIN_TABLE_3_FP64;
7129
+ }
7130
+ #endif
7326
7131
 
7327
- fn lighting_getLightColor2(surfaceColor: vec3<f32>, cameraPosition: vec3<f32>, position_worldspace: vec3<f32>, normal_worldspace: vec3<f32>) -> vec3<f32> {
7328
- var lightColor: vec3<f32> = surfaceColor;
7132
+ vec2 sin_t, cos_t;
7133
+ sincos_taylor_fp64(t, sin_t, cos_t);
7329
7134
 
7330
- if (lighting.enabled == 0) {
7331
- return lightColor;
7332
- }
7333
7135
 
7334
- let view_direction: vec3<f32> = normalize(cameraPosition - position_worldspace);
7335
- lightColor = material.ambient * surfaceColor * lighting.ambientColor;
7336
7136
 
7337
- if (lighting.lightType == 0) {
7338
- let pointLight: PointLight = lighting_getPointLight(0);
7339
- let light_position_worldspace: vec3<f32> = pointLight.position;
7340
- let light_direction: vec3<f32> = normalize(light_position_worldspace - position_worldspace);
7341
- lightColor += lighting_getLightColor(surfaceColor, light_direction, view_direction, normal_worldspace, pointLight.color);
7342
- } else if (lighting.lightType == 1) {
7343
- var directionalLight: DirectionalLight = lighting_getDirectionalLight(0);
7344
- lightColor += lighting_getLightColor(surfaceColor, -directionalLight.direction, view_direction, normal_worldspace, directionalLight.color);
7345
- }
7346
-
7347
- return lightColor;
7348
- /*
7349
- for (int i = 0; i < MAX_LIGHTS; i++) {
7350
- if (i >= lighting.pointLightCount) {
7351
- break;
7137
+ vec2 result = vec2(0.0, 0.0);
7138
+ if (j == 0) {
7139
+ if (k > 0) {
7140
+ result = sum_fp64(mul_fp64(u, sin_t), mul_fp64(v, cos_t));
7141
+ } else {
7142
+ result = sub_fp64(mul_fp64(u, sin_t), mul_fp64(v, cos_t));
7143
+ }
7144
+ } else if (j == 1) {
7145
+ if (k > 0) {
7146
+ result = sub_fp64(mul_fp64(u, cos_t), mul_fp64(v, sin_t));
7147
+ } else {
7148
+ result = sum_fp64(mul_fp64(u, cos_t), mul_fp64(v, sin_t));
7149
+ }
7150
+ } else if (j == -1) {
7151
+ if (k > 0) {
7152
+ result = sub_fp64(mul_fp64(v, sin_t), mul_fp64(u, cos_t));
7153
+ } else {
7154
+ result = -sum_fp64(mul_fp64(v, sin_t), mul_fp64(u, cos_t));
7155
+ }
7156
+ } else {
7157
+ if (k > 0) {
7158
+ result = -sum_fp64(mul_fp64(u, sin_t), mul_fp64(v, cos_t));
7159
+ } else {
7160
+ result = sub_fp64(mul_fp64(v, cos_t), mul_fp64(u, sin_t));
7161
+ }
7352
7162
  }
7353
- PointLight pointLight = lighting.pointLight[i];
7354
- vec3 light_position_worldspace = pointLight.position;
7355
- vec3 light_direction = normalize(light_position_worldspace - position_worldspace);
7356
- lightColor += lighting_getLightColor(surfaceColor, light_direction, view_direction, normal_worldspace, pointLight.color);
7357
- }
7358
7163
 
7359
- for (int i = 0; i < MAX_LIGHTS; i++) {
7360
- if (i >= lighting.directionalLightCount) {
7361
- break;
7362
- }
7363
- DirectionalLight directionalLight = lighting.directionalLight[i];
7364
- lightColor += lighting_getLightColor(surfaceColor, -directionalLight.direction, view_direction, normal_worldspace, directionalLight.color);
7365
- }
7366
- */
7164
+ return result;
7367
7165
  }
7368
7166
 
7369
- fn lighting_getSpecularLightColor(cameraPosition: vec3<f32>, position_worldspace: vec3<f32>, normal_worldspace: vec3<f32>) -> vec3<f32>{
7370
- var lightColor = vec3<f32>(0, 0, 0);
7371
- let surfaceColor = vec3<f32>(0, 0, 0);
7167
+ vec2 cos_fp64(vec2 a) {
7168
+ if (a.x == 0.0 && a.y == 0.0) {
7169
+ return vec2(1.0, 0.0);
7170
+ }
7372
7171
 
7373
- if (lighting.enabled == 0) {
7374
- let view_direction = normalize(cameraPosition - position_worldspace);
7172
+ // 2pi range reduction
7173
+ vec2 z = nint_fp64(div_fp64(a, TWO_PI_FP64));
7174
+ vec2 r = sub_fp64(a, mul_fp64(TWO_PI_FP64, z));
7375
7175
 
7376
- switch (lighting.lightType) {
7377
- case 0, default: {
7378
- let pointLight: PointLight = lighting_getPointLight(0);
7379
- let light_position_worldspace: vec3<f32> = pointLight.position;
7380
- let light_direction: vec3<f32> = normalize(light_position_worldspace - position_worldspace);
7381
- lightColor += lighting_getLightColor(surfaceColor, light_direction, view_direction, normal_worldspace, pointLight.color);
7382
- }
7383
- case 1: {
7384
- let directionalLight: DirectionalLight = lighting_getDirectionalLight(0);
7385
- lightColor += lighting_getLightColor(surfaceColor, -directionalLight.direction, view_direction, normal_worldspace, directionalLight.color);
7386
- }
7387
- }
7388
- }
7389
- return lightColor;
7390
- }
7391
- `
7392
- );
7176
+ vec2 t;
7177
+ float q = floor(r.x / PI_2_FP64.x + 0.5);
7178
+ int j = int(q);
7393
7179
 
7394
- // src/modules/lighting/phong-material/phong-material.ts
7395
- var phongMaterial = {
7396
- name: "phongMaterial",
7397
- dependencies: [lighting],
7398
- // Note these are switched between phong and gouraud
7399
- source: PHONG_WGSL,
7400
- vs: PHONG_VS,
7401
- fs: PHONG_FS,
7402
- defines: {
7403
- LIGHTING_FRAGMENT: 1
7404
- },
7405
- uniformTypes: {
7406
- ambient: "f32",
7407
- diffuse: "f32",
7408
- shininess: "f32",
7409
- specularColor: "vec3<f32>"
7410
- },
7411
- defaultUniforms: {
7412
- ambient: 0.35,
7413
- diffuse: 0.6,
7414
- shininess: 32,
7415
- specularColor: [0.15, 0.15, 0.15]
7416
- },
7417
- getUniforms(props) {
7418
- const uniforms = { ...props };
7419
- if (uniforms.specularColor) {
7420
- uniforms.specularColor = uniforms.specularColor.map((x) => x / 255);
7421
- }
7422
- return { ...phongMaterial.defaultUniforms, ...uniforms };
7180
+ if (j < -2 || j > 2) {
7181
+ return vec2(0.0 / 0.0, 0.0 / 0.0);
7423
7182
  }
7424
- };
7425
7183
 
7426
- // src/modules/lighting/pbr-material/pbr-vertex-glsl.ts
7427
- var vs2 = (
7428
- /* glsl */
7429
- `out vec3 pbr_vPosition;
7430
- out vec2 pbr_vUV;
7184
+ t = sub_fp64(r, mul_fp64(PI_2_FP64, vec2(q, 0.0)));
7431
7185
 
7432
- #ifdef HAS_NORMALS
7433
- # ifdef HAS_TANGENTS
7434
- out mat3 pbr_vTBN;
7435
- # else
7436
- out vec3 pbr_vNormal;
7437
- # endif
7438
- #endif
7186
+ q = floor(t.x / PI_16_FP64.x + 0.5);
7187
+ int k = int(q);
7439
7188
 
7440
- void pbr_setPositionNormalTangentUV(vec4 position, vec4 normal, vec4 tangent, vec2 uv)
7441
- {
7442
- vec4 pos = pbrProjection.modelMatrix * position;
7443
- pbr_vPosition = vec3(pos.xyz) / pos.w;
7189
+ if (k == 0) {
7190
+ if (j == 0) {
7191
+ return cos_taylor_fp64(t);
7192
+ } else if (j == 1) {
7193
+ return -sin_taylor_fp64(t);
7194
+ } else if (j == -1) {
7195
+ return sin_taylor_fp64(t);
7196
+ } else {
7197
+ return -cos_taylor_fp64(t);
7198
+ }
7199
+ }
7444
7200
 
7445
- #ifdef HAS_NORMALS
7446
- #ifdef HAS_TANGENTS
7447
- vec3 normalW = normalize(vec3(pbrProjection.normalMatrix * vec4(normal.xyz, 0.0)));
7448
- vec3 tangentW = normalize(vec3(pbrProjection.modelMatrix * vec4(tangent.xyz, 0.0)));
7449
- vec3 bitangentW = cross(normalW, tangentW) * tangent.w;
7450
- pbr_vTBN = mat3(tangentW, bitangentW, normalW);
7451
- #else // HAS_TANGENTS != 1
7452
- pbr_vNormal = normalize(vec3(pbrProjection.modelMatrix * vec4(normal.xyz, 0.0)));
7453
- #endif
7454
- #endif
7201
+ int abs_k = int(abs(float(k)));
7455
7202
 
7456
- #ifdef HAS_UV
7457
- pbr_vUV = uv;
7203
+ if (abs_k > 4) {
7204
+ return vec2(0.0 / 0.0, 0.0 / 0.0);
7205
+ } else {
7206
+ t = sub_fp64(t, mul_fp64(PI_16_FP64, vec2(q, 0.0)));
7207
+ }
7208
+
7209
+ vec2 u = vec2(0.0, 0.0);
7210
+ vec2 v = vec2(0.0, 0.0);
7211
+
7212
+ #if defined(NVIDIA_FP64_WORKAROUND) || defined(INTEL_FP64_WORKAROUND)
7213
+ if (abs(float(abs_k) - 1.0) < 0.5) {
7214
+ u = COS_TABLE_0_FP64;
7215
+ v = SIN_TABLE_0_FP64;
7216
+ } else if (abs(float(abs_k) - 2.0) < 0.5) {
7217
+ u = COS_TABLE_1_FP64;
7218
+ v = SIN_TABLE_1_FP64;
7219
+ } else if (abs(float(abs_k) - 3.0) < 0.5) {
7220
+ u = COS_TABLE_2_FP64;
7221
+ v = SIN_TABLE_2_FP64;
7222
+ } else if (abs(float(abs_k) - 4.0) < 0.5) {
7223
+ u = COS_TABLE_3_FP64;
7224
+ v = SIN_TABLE_3_FP64;
7225
+ }
7458
7226
  #else
7459
- pbr_vUV = vec2(0.,0.);
7227
+ if (abs_k == 1) {
7228
+ u = COS_TABLE_0_FP64;
7229
+ v = SIN_TABLE_0_FP64;
7230
+ } else if (abs_k == 2) {
7231
+ u = COS_TABLE_1_FP64;
7232
+ v = SIN_TABLE_1_FP64;
7233
+ } else if (abs_k == 3) {
7234
+ u = COS_TABLE_2_FP64;
7235
+ v = SIN_TABLE_2_FP64;
7236
+ } else if (abs_k == 4) {
7237
+ u = COS_TABLE_3_FP64;
7238
+ v = SIN_TABLE_3_FP64;
7239
+ }
7460
7240
  #endif
7461
- }
7462
- `
7463
- );
7464
7241
 
7465
- // src/modules/lighting/pbr-material/pbr-fragment-glsl.ts
7466
- var fs3 = (
7467
- /* glsl */
7468
- `precision highp float;
7242
+ vec2 sin_t, cos_t;
7243
+ sincos_taylor_fp64(t, sin_t, cos_t);
7469
7244
 
7470
- uniform pbrMaterialUniforms {
7471
- // Material is unlit
7472
- bool unlit;
7245
+ vec2 result = vec2(0.0, 0.0);
7246
+ if (j == 0) {
7247
+ if (k > 0) {
7248
+ result = sub_fp64(mul_fp64(u, cos_t), mul_fp64(v, sin_t));
7249
+ } else {
7250
+ result = sum_fp64(mul_fp64(u, cos_t), mul_fp64(v, sin_t));
7251
+ }
7252
+ } else if (j == 1) {
7253
+ if (k > 0) {
7254
+ result = -sum_fp64(mul_fp64(u, sin_t), mul_fp64(v, cos_t));
7255
+ } else {
7256
+ result = sub_fp64(mul_fp64(v, cos_t), mul_fp64(u, sin_t));
7257
+ }
7258
+ } else if (j == -1) {
7259
+ if (k > 0) {
7260
+ result = sum_fp64(mul_fp64(u, sin_t), mul_fp64(v, cos_t));
7261
+ } else {
7262
+ result = sub_fp64(mul_fp64(u, sin_t), mul_fp64(v, cos_t));
7263
+ }
7264
+ } else {
7265
+ if (k > 0) {
7266
+ result = sub_fp64(mul_fp64(v, sin_t), mul_fp64(u, cos_t));
7267
+ } else {
7268
+ result = -sum_fp64(mul_fp64(u, cos_t), mul_fp64(v, sin_t));
7269
+ }
7270
+ }
7473
7271
 
7474
- // Base color map
7475
- bool baseColorMapEnabled;
7476
- vec4 baseColorFactor;
7272
+ return result;
7273
+ }
7477
7274
 
7478
- bool normalMapEnabled;
7479
- float normalScale; // #ifdef HAS_NORMALMAP
7275
+ vec2 tan_fp64(vec2 a) {
7276
+ vec2 sin_a;
7277
+ vec2 cos_a;
7480
7278
 
7481
- bool emissiveMapEnabled;
7482
- vec3 emissiveFactor; // #ifdef HAS_EMISSIVEMAP
7279
+ if (a.x == 0.0 && a.y == 0.0) {
7280
+ return vec2(0.0, 0.0);
7281
+ }
7483
7282
 
7484
- vec2 metallicRoughnessValues;
7485
- bool metallicRoughnessMapEnabled;
7283
+ // 2pi range reduction
7284
+ vec2 z = nint_fp64(div_fp64(a, TWO_PI_FP64));
7285
+ vec2 r = sub_fp64(a, mul_fp64(TWO_PI_FP64, z));
7486
7286
 
7487
- bool occlusionMapEnabled;
7488
- float occlusionStrength; // #ifdef HAS_OCCLUSIONMAP
7489
-
7490
- bool alphaCutoffEnabled;
7491
- float alphaCutoff; // #ifdef ALPHA_CUTOFF
7492
-
7493
- // IBL
7494
- bool IBLenabled;
7495
- vec2 scaleIBLAmbient; // #ifdef USE_IBL
7496
-
7497
- // debugging flags used for shader output of intermediate PBR variables
7498
- // #ifdef PBR_DEBUG
7499
- vec4 scaleDiffBaseMR;
7500
- vec4 scaleFGDSpec;
7501
- // #endif
7502
- } pbrMaterial;
7287
+ vec2 t;
7288
+ float q = floor(r.x / PI_2_FP64.x + 0.5);
7289
+ int j = int(q);
7503
7290
 
7504
- // Samplers
7505
- #ifdef HAS_BASECOLORMAP
7506
- uniform sampler2D pbr_baseColorSampler;
7507
- #endif
7508
- #ifdef HAS_NORMALMAP
7509
- uniform sampler2D pbr_normalSampler;
7510
- #endif
7511
- #ifdef HAS_EMISSIVEMAP
7512
- uniform sampler2D pbr_emissiveSampler;
7513
- #endif
7514
- #ifdef HAS_METALROUGHNESSMAP
7515
- uniform sampler2D pbr_metallicRoughnessSampler;
7516
- #endif
7517
- #ifdef HAS_OCCLUSIONMAP
7518
- uniform sampler2D pbr_occlusionSampler;
7519
- #endif
7520
- #ifdef USE_IBL
7521
- uniform samplerCube pbr_diffuseEnvSampler;
7522
- uniform samplerCube pbr_specularEnvSampler;
7523
- uniform sampler2D pbr_brdfLUT;
7524
- #endif
7525
7291
 
7526
- // Inputs from vertex shader
7292
+ if (j < -2 || j > 2) {
7293
+ return vec2(0.0 / 0.0, 0.0 / 0.0);
7294
+ }
7527
7295
 
7528
- in vec3 pbr_vPosition;
7529
- in vec2 pbr_vUV;
7296
+ t = sub_fp64(r, mul_fp64(PI_2_FP64, vec2(q, 0.0)));
7530
7297
 
7531
- #ifdef HAS_NORMALS
7532
- #ifdef HAS_TANGENTS
7533
- in mat3 pbr_vTBN;
7534
- #else
7535
- in vec3 pbr_vNormal;
7536
- #endif
7537
- #endif
7298
+ q = floor(t.x / PI_16_FP64.x + 0.5);
7299
+ int k = int(q);
7300
+ int abs_k = int(abs(float(k)));
7538
7301
 
7539
- // Encapsulate the various inputs used by the various functions in the shading equation
7540
- // We store values in this struct to simplify the integration of alternative implementations
7541
- // of the shading terms, outlined in the Readme.MD Appendix.
7542
- struct PBRInfo {
7543
- float NdotL; // cos angle between normal and light direction
7544
- float NdotV; // cos angle between normal and view direction
7545
- float NdotH; // cos angle between normal and half vector
7546
- float LdotH; // cos angle between light direction and half vector
7547
- float VdotH; // cos angle between view direction and half vector
7548
- float perceptualRoughness; // roughness value, as authored by the model creator (input to shader)
7549
- float metalness; // metallic value at the surface
7550
- vec3 reflectance0; // full reflectance color (normal incidence angle)
7551
- vec3 reflectance90; // reflectance color at grazing angle
7552
- float alphaRoughness; // roughness mapped to a more linear change in the roughness (proposed by [2])
7553
- vec3 diffuseColor; // color contribution from diffuse lighting
7554
- vec3 specularColor; // color contribution from specular lighting
7555
- vec3 n; // normal at surface point
7556
- vec3 v; // vector from surface point to camera
7557
- };
7302
+ // We just can't get PI/16 * 3.0 very accurately.
7303
+ // so let's just store it
7304
+ if (abs_k > 4) {
7305
+ return vec2(0.0 / 0.0, 0.0 / 0.0);
7306
+ } else {
7307
+ t = sub_fp64(t, mul_fp64(PI_16_FP64, vec2(q, 0.0)));
7308
+ }
7558
7309
 
7559
- const float M_PI = 3.141592653589793;
7560
- const float c_MinRoughness = 0.04;
7561
7310
 
7562
- vec4 SRGBtoLINEAR(vec4 srgbIn)
7563
- {
7564
- #ifdef MANUAL_SRGB
7565
- #ifdef SRGB_FAST_APPROXIMATION
7566
- vec3 linOut = pow(srgbIn.xyz,vec3(2.2));
7567
- #else // SRGB_FAST_APPROXIMATION
7568
- vec3 bLess = step(vec3(0.04045),srgbIn.xyz);
7569
- vec3 linOut = mix( srgbIn.xyz/vec3(12.92), pow((srgbIn.xyz+vec3(0.055))/vec3(1.055),vec3(2.4)), bLess );
7570
- #endif //SRGB_FAST_APPROXIMATION
7571
- return vec4(linOut,srgbIn.w);;
7572
- #else //MANUAL_SRGB
7573
- return srgbIn;
7574
- #endif //MANUAL_SRGB
7575
- }
7311
+ vec2 u = vec2(0.0, 0.0);
7312
+ vec2 v = vec2(0.0, 0.0);
7576
7313
 
7577
- // Find the normal for this fragment, pulling either from a predefined normal map
7578
- // or from the interpolated mesh normal and tangent attributes.
7579
- vec3 getNormal()
7580
- {
7581
- // Retrieve the tangent space matrix
7582
- #ifndef HAS_TANGENTS
7583
- vec3 pos_dx = dFdx(pbr_vPosition);
7584
- vec3 pos_dy = dFdy(pbr_vPosition);
7585
- vec3 tex_dx = dFdx(vec3(pbr_vUV, 0.0));
7586
- vec3 tex_dy = dFdy(vec3(pbr_vUV, 0.0));
7587
- vec3 t = (tex_dy.t * pos_dx - tex_dx.t * pos_dy) / (tex_dx.s * tex_dy.t - tex_dy.s * tex_dx.t);
7314
+ vec2 sin_t, cos_t;
7315
+ vec2 s, c;
7316
+ sincos_taylor_fp64(t, sin_t, cos_t);
7588
7317
 
7589
- #ifdef HAS_NORMALS
7590
- vec3 ng = normalize(pbr_vNormal);
7318
+ if (k == 0) {
7319
+ s = sin_t;
7320
+ c = cos_t;
7321
+ } else {
7322
+ #if defined(NVIDIA_FP64_WORKAROUND) || defined(INTEL_FP64_WORKAROUND)
7323
+ if (abs(float(abs_k) - 1.0) < 0.5) {
7324
+ u = COS_TABLE_0_FP64;
7325
+ v = SIN_TABLE_0_FP64;
7326
+ } else if (abs(float(abs_k) - 2.0) < 0.5) {
7327
+ u = COS_TABLE_1_FP64;
7328
+ v = SIN_TABLE_1_FP64;
7329
+ } else if (abs(float(abs_k) - 3.0) < 0.5) {
7330
+ u = COS_TABLE_2_FP64;
7331
+ v = SIN_TABLE_2_FP64;
7332
+ } else if (abs(float(abs_k) - 4.0) < 0.5) {
7333
+ u = COS_TABLE_3_FP64;
7334
+ v = SIN_TABLE_3_FP64;
7335
+ }
7591
7336
  #else
7592
- vec3 ng = cross(pos_dx, pos_dy);
7593
- #endif
7594
-
7595
- t = normalize(t - ng * dot(ng, t));
7596
- vec3 b = normalize(cross(ng, t));
7597
- mat3 tbn = mat3(t, b, ng);
7598
- #else // HAS_TANGENTS
7599
- mat3 tbn = pbr_vTBN;
7337
+ if (abs_k == 1) {
7338
+ u = COS_TABLE_0_FP64;
7339
+ v = SIN_TABLE_0_FP64;
7340
+ } else if (abs_k == 2) {
7341
+ u = COS_TABLE_1_FP64;
7342
+ v = SIN_TABLE_1_FP64;
7343
+ } else if (abs_k == 3) {
7344
+ u = COS_TABLE_2_FP64;
7345
+ v = SIN_TABLE_2_FP64;
7346
+ } else if (abs_k == 4) {
7347
+ u = COS_TABLE_3_FP64;
7348
+ v = SIN_TABLE_3_FP64;
7349
+ }
7600
7350
  #endif
7351
+ if (k > 0) {
7352
+ s = sum_fp64(mul_fp64(u, sin_t), mul_fp64(v, cos_t));
7353
+ c = sub_fp64(mul_fp64(u, cos_t), mul_fp64(v, sin_t));
7354
+ } else {
7355
+ s = sub_fp64(mul_fp64(u, sin_t), mul_fp64(v, cos_t));
7356
+ c = sum_fp64(mul_fp64(u, cos_t), mul_fp64(v, sin_t));
7357
+ }
7358
+ }
7601
7359
 
7602
- #ifdef HAS_NORMALMAP
7603
- vec3 n = texture(pbr_normalSampler, pbr_vUV).rgb;
7604
- n = normalize(tbn * ((2.0 * n - 1.0) * vec3(pbrMaterial.normalScale, pbrMaterial.normalScale, 1.0)));
7605
- #else
7606
- // The tbn matrix is linearly interpolated, so we need to re-normalize
7607
- vec3 n = normalize(tbn[2].xyz);
7608
- #endif
7360
+ if (j == 0) {
7361
+ sin_a = s;
7362
+ cos_a = c;
7363
+ } else if (j == 1) {
7364
+ sin_a = c;
7365
+ cos_a = -s;
7366
+ } else if (j == -1) {
7367
+ sin_a = -c;
7368
+ cos_a = s;
7369
+ } else {
7370
+ sin_a = -s;
7371
+ cos_a = -c;
7372
+ }
7373
+ return div_fp64(sin_a, cos_a);
7374
+ }
7609
7375
 
7610
- return n;
7376
+ vec2 radians_fp64(vec2 degree) {
7377
+ return mul_fp64(degree, PI_180_FP64);
7611
7378
  }
7612
7379
 
7613
- // Calculation of the lighting contribution from an optional Image Based Light source.
7614
- // Precomputed Environment Maps are required uniform inputs and are computed as outlined in [1].
7615
- // See our README.md on Environment Maps [3] for additional discussion.
7616
- #ifdef USE_IBL
7617
- vec3 getIBLContribution(PBRInfo pbrInfo, vec3 n, vec3 reflection)
7618
- {
7619
- float mipCount = 9.0; // resolution of 512x512
7620
- float lod = (pbrInfo.perceptualRoughness * mipCount);
7621
- // retrieve a scale and bias to F0. See [1], Figure 3
7622
- vec3 brdf = SRGBtoLINEAR(texture(pbr_brdfLUT,
7623
- vec2(pbrInfo.NdotV, 1.0 - pbrInfo.perceptualRoughness))).rgb;
7624
- vec3 diffuseLight = SRGBtoLINEAR(texture(pbr_diffuseEnvSampler, n)).rgb;
7380
+ vec2 mix_fp64(vec2 a, vec2 b, float x) {
7381
+ vec2 range = sub_fp64(b, a);
7382
+ return sum_fp64(a, mul_fp64(range, vec2(x, 0.0)));
7383
+ }
7625
7384
 
7626
- #ifdef USE_TEX_LOD
7627
- vec3 specularLight = SRGBtoLINEAR(texture(pbr_specularEnvSampler, reflection, lod)).rgb;
7628
- #else
7629
- vec3 specularLight = SRGBtoLINEAR(texture(pbr_specularEnvSampler, reflection)).rgb;
7630
- #endif
7385
+ // Vector functions
7386
+ // vec2 functions
7387
+ void vec2_sum_fp64(vec2 a[2], vec2 b[2], out vec2 out_val[2]) {
7388
+ out_val[0] = sum_fp64(a[0], b[0]);
7389
+ out_val[1] = sum_fp64(a[1], b[1]);
7390
+ }
7631
7391
 
7632
- vec3 diffuse = diffuseLight * pbrInfo.diffuseColor;
7633
- vec3 specular = specularLight * (pbrInfo.specularColor * brdf.x + brdf.y);
7392
+ void vec2_sub_fp64(vec2 a[2], vec2 b[2], out vec2 out_val[2]) {
7393
+ out_val[0] = sub_fp64(a[0], b[0]);
7394
+ out_val[1] = sub_fp64(a[1], b[1]);
7395
+ }
7634
7396
 
7635
- // For presentation, this allows us to disable IBL terms
7636
- diffuse *= pbrMaterial.scaleIBLAmbient.x;
7637
- specular *= pbrMaterial.scaleIBLAmbient.y;
7397
+ void vec2_mul_fp64(vec2 a[2], vec2 b[2], out vec2 out_val[2]) {
7398
+ out_val[0] = mul_fp64(a[0], b[0]);
7399
+ out_val[1] = mul_fp64(a[1], b[1]);
7400
+ }
7638
7401
 
7639
- return diffuse + specular;
7402
+ void vec2_div_fp64(vec2 a[2], vec2 b[2], out vec2 out_val[2]) {
7403
+ out_val[0] = div_fp64(a[0], b[0]);
7404
+ out_val[1] = div_fp64(a[1], b[1]);
7640
7405
  }
7641
- #endif
7642
7406
 
7643
- // Basic Lambertian diffuse
7644
- // Implementation from Lambert's Photometria https://archive.org/details/lambertsphotome00lambgoog
7645
- // See also [1], Equation 1
7646
- vec3 diffuse(PBRInfo pbrInfo)
7647
- {
7648
- return pbrInfo.diffuseColor / M_PI;
7407
+ void vec2_mix_fp64(vec2 x[2], vec2 y[2], float a, out vec2 out_val[2]) {
7408
+ vec2 range[2];
7409
+ vec2_sub_fp64(y, x, range);
7410
+ vec2 portion[2];
7411
+ portion[0] = range[0] * a;
7412
+ portion[1] = range[1] * a;
7413
+ vec2_sum_fp64(x, portion, out_val);
7649
7414
  }
7650
7415
 
7651
- // The following equation models the Fresnel reflectance term of the spec equation (aka F())
7652
- // Implementation of fresnel from [4], Equation 15
7653
- vec3 specularReflection(PBRInfo pbrInfo)
7654
- {
7655
- return pbrInfo.reflectance0 +
7656
- (pbrInfo.reflectance90 - pbrInfo.reflectance0) *
7657
- pow(clamp(1.0 - pbrInfo.VdotH, 0.0, 1.0), 5.0);
7416
+ vec2 vec2_length_fp64(vec2 x[2]) {
7417
+ return sqrt_fp64(sum_fp64(mul_fp64(x[0], x[0]), mul_fp64(x[1], x[1])));
7658
7418
  }
7659
7419
 
7660
- // This calculates the specular geometric attenuation (aka G()),
7661
- // where rougher material will reflect less light back to the viewer.
7662
- // This implementation is based on [1] Equation 4, and we adopt their modifications to
7663
- // alphaRoughness as input as originally proposed in [2].
7664
- float geometricOcclusion(PBRInfo pbrInfo)
7665
- {
7666
- float NdotL = pbrInfo.NdotL;
7667
- float NdotV = pbrInfo.NdotV;
7668
- float r = pbrInfo.alphaRoughness;
7420
+ void vec2_normalize_fp64(vec2 x[2], out vec2 out_val[2]) {
7421
+ vec2 length = vec2_length_fp64(x);
7422
+ vec2 length_vec2[2];
7423
+ length_vec2[0] = length;
7424
+ length_vec2[1] = length;
7669
7425
 
7670
- float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL)));
7671
- float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV)));
7672
- return attenuationL * attenuationV;
7426
+ vec2_div_fp64(x, length_vec2, out_val);
7673
7427
  }
7674
7428
 
7675
- // The following equation(s) model the distribution of microfacet normals across
7676
- // the area being drawn (aka D())
7677
- // Implementation from "Average Irregularity Representation of a Roughened Surface
7678
- // for Ray Reflection" by T. S. Trowbridge, and K. P. Reitz
7679
- // Follows the distribution function recommended in the SIGGRAPH 2013 course notes
7680
- // from EPIC Games [1], Equation 3.
7681
- float microfacetDistribution(PBRInfo pbrInfo)
7682
- {
7683
- float roughnessSq = pbrInfo.alphaRoughness * pbrInfo.alphaRoughness;
7684
- float f = (pbrInfo.NdotH * roughnessSq - pbrInfo.NdotH) * pbrInfo.NdotH + 1.0;
7685
- return roughnessSq / (M_PI * f * f);
7429
+ vec2 vec2_distance_fp64(vec2 x[2], vec2 y[2]) {
7430
+ vec2 diff[2];
7431
+ vec2_sub_fp64(x, y, diff);
7432
+ return vec2_length_fp64(diff);
7686
7433
  }
7687
7434
 
7688
- void PBRInfo_setAmbientLight(inout PBRInfo pbrInfo) {
7689
- pbrInfo.NdotL = 1.0;
7690
- pbrInfo.NdotH = 0.0;
7691
- pbrInfo.LdotH = 0.0;
7692
- pbrInfo.VdotH = 1.0;
7693
- }
7435
+ vec2 vec2_dot_fp64(vec2 a[2], vec2 b[2]) {
7436
+ vec2 v[2];
7694
7437
 
7695
- void PBRInfo_setDirectionalLight(inout PBRInfo pbrInfo, vec3 lightDirection) {
7696
- vec3 n = pbrInfo.n;
7697
- vec3 v = pbrInfo.v;
7698
- vec3 l = normalize(lightDirection); // Vector from surface point to light
7699
- vec3 h = normalize(l+v); // Half vector between both l and v
7438
+ v[0] = mul_fp64(a[0], b[0]);
7439
+ v[1] = mul_fp64(a[1], b[1]);
7700
7440
 
7701
- pbrInfo.NdotL = clamp(dot(n, l), 0.001, 1.0);
7702
- pbrInfo.NdotH = clamp(dot(n, h), 0.0, 1.0);
7703
- pbrInfo.LdotH = clamp(dot(l, h), 0.0, 1.0);
7704
- pbrInfo.VdotH = clamp(dot(v, h), 0.0, 1.0);
7441
+ return sum_fp64(v[0], v[1]);
7705
7442
  }
7706
7443
 
7707
- void PBRInfo_setPointLight(inout PBRInfo pbrInfo, PointLight pointLight) {
7708
- vec3 light_direction = normalize(pointLight.position - pbr_vPosition);
7709
- PBRInfo_setDirectionalLight(pbrInfo, light_direction);
7444
+ // vec3 functions
7445
+ void vec3_sub_fp64(vec2 a[3], vec2 b[3], out vec2 out_val[3]) {
7446
+ for (int i = 0; i < 3; i++) {
7447
+ out_val[i] = sum_fp64(a[i], b[i]);
7448
+ }
7710
7449
  }
7711
7450
 
7712
- vec3 calculateFinalColor(PBRInfo pbrInfo, vec3 lightColor) {
7713
- // Calculate the shading terms for the microfacet specular shading model
7714
- vec3 F = specularReflection(pbrInfo);
7715
- float G = geometricOcclusion(pbrInfo);
7716
- float D = microfacetDistribution(pbrInfo);
7451
+ void vec3_sum_fp64(vec2 a[3], vec2 b[3], out vec2 out_val[3]) {
7452
+ for (int i = 0; i < 3; i++) {
7453
+ out_val[i] = sum_fp64(a[i], b[i]);
7454
+ }
7455
+ }
7717
7456
 
7718
- // Calculation of analytical lighting contribution
7719
- vec3 diffuseContrib = (1.0 - F) * diffuse(pbrInfo);
7720
- vec3 specContrib = F * G * D / (4.0 * pbrInfo.NdotL * pbrInfo.NdotV);
7721
- // Obtain final intensity as reflectance (BRDF) scaled by the energy of the light (cosine law)
7722
- return pbrInfo.NdotL * lightColor * (diffuseContrib + specContrib);
7457
+ vec2 vec3_length_fp64(vec2 x[3]) {
7458
+ return sqrt_fp64(sum_fp64(sum_fp64(mul_fp64(x[0], x[0]), mul_fp64(x[1], x[1])),
7459
+ mul_fp64(x[2], x[2])));
7723
7460
  }
7724
7461
 
7725
- vec4 pbr_filterColor(vec4 colorUnused)
7726
- {
7727
- // The albedo may be defined from a base texture or a flat color
7728
- #ifdef HAS_BASECOLORMAP
7729
- vec4 baseColor = SRGBtoLINEAR(texture(pbr_baseColorSampler, pbr_vUV)) * pbrMaterial.baseColorFactor;
7730
- #else
7731
- vec4 baseColor = pbrMaterial.baseColorFactor;
7732
- #endif
7462
+ vec2 vec3_distance_fp64(vec2 x[3], vec2 y[3]) {
7463
+ vec2 diff[3];
7464
+ vec3_sub_fp64(x, y, diff);
7465
+ return vec3_length_fp64(diff);
7466
+ }
7733
7467
 
7734
- #ifdef ALPHA_CUTOFF
7735
- if (baseColor.a < pbrMaterial.alphaCutoff) {
7736
- discard;
7737
- }
7738
- #endif
7468
+ // vec4 functions
7469
+ void vec4_fp64(vec4 a, out vec2 out_val[4]) {
7470
+ out_val[0].x = a[0];
7471
+ out_val[0].y = 0.0;
7739
7472
 
7740
- vec3 color = vec3(0, 0, 0);
7473
+ out_val[1].x = a[1];
7474
+ out_val[1].y = 0.0;
7741
7475
 
7742
- if(pbrMaterial.unlit){
7743
- color.rgb = baseColor.rgb;
7476
+ out_val[2].x = a[2];
7477
+ out_val[2].y = 0.0;
7478
+
7479
+ out_val[3].x = a[3];
7480
+ out_val[3].y = 0.0;
7481
+ }
7482
+
7483
+ void vec4_scalar_mul_fp64(vec2 a[4], vec2 b, out vec2 out_val[4]) {
7484
+ out_val[0] = mul_fp64(a[0], b);
7485
+ out_val[1] = mul_fp64(a[1], b);
7486
+ out_val[2] = mul_fp64(a[2], b);
7487
+ out_val[3] = mul_fp64(a[3], b);
7488
+ }
7489
+
7490
+ void vec4_sum_fp64(vec2 a[4], vec2 b[4], out vec2 out_val[4]) {
7491
+ for (int i = 0; i < 4; i++) {
7492
+ out_val[i] = sum_fp64(a[i], b[i]);
7744
7493
  }
7745
- else{
7746
- // Metallic and Roughness material properties are packed together
7747
- // In glTF, these factors can be specified by fixed scalar values
7748
- // or from a metallic-roughness map
7749
- float perceptualRoughness = pbrMaterial.metallicRoughnessValues.y;
7750
- float metallic = pbrMaterial.metallicRoughnessValues.x;
7751
- #ifdef HAS_METALROUGHNESSMAP
7752
- // Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel.
7753
- // This layout intentionally reserves the 'r' channel for (optional) occlusion map data
7754
- vec4 mrSample = texture(pbr_metallicRoughnessSampler, pbr_vUV);
7755
- perceptualRoughness = mrSample.g * perceptualRoughness;
7756
- metallic = mrSample.b * metallic;
7757
- #endif
7758
- perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);
7759
- metallic = clamp(metallic, 0.0, 1.0);
7760
- // Roughness is authored as perceptual roughness; as is convention,
7761
- // convert to material roughness by squaring the perceptual roughness [2].
7762
- float alphaRoughness = perceptualRoughness * perceptualRoughness;
7494
+ }
7763
7495
 
7764
- vec3 f0 = vec3(0.04);
7765
- vec3 diffuseColor = baseColor.rgb * (vec3(1.0) - f0);
7766
- diffuseColor *= 1.0 - metallic;
7767
- vec3 specularColor = mix(f0, baseColor.rgb, metallic);
7496
+ void vec4_dot_fp64(vec2 a[4], vec2 b[4], out vec2 out_val) {
7497
+ vec2 v[4];
7768
7498
 
7769
- // Compute reflectance.
7770
- float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
7499
+ v[0] = mul_fp64(a[0], b[0]);
7500
+ v[1] = mul_fp64(a[1], b[1]);
7501
+ v[2] = mul_fp64(a[2], b[2]);
7502
+ v[3] = mul_fp64(a[3], b[3]);
7771
7503
 
7772
- // For typical incident reflectance range (between 4% to 100%) set the grazing
7773
- // reflectance to 100% for typical fresnel effect.
7774
- // For very low reflectance range on highly diffuse objects (below 4%),
7775
- // incrementally reduce grazing reflecance to 0%.
7776
- float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);
7777
- vec3 specularEnvironmentR0 = specularColor.rgb;
7778
- vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90;
7504
+ out_val = sum_fp64(sum_fp64(v[0], v[1]), sum_fp64(v[2], v[3]));
7505
+ }
7779
7506
 
7780
- vec3 n = getNormal(); // normal at surface point
7781
- vec3 v = normalize(pbrProjection.camera - pbr_vPosition); // Vector from surface point to camera
7507
+ void mat4_vec4_mul_fp64(vec2 b[16], vec2 a[4], out vec2 out_val[4]) {
7508
+ vec2 tmp[4];
7782
7509
 
7783
- float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
7784
- vec3 reflection = -normalize(reflect(v, n));
7510
+ for (int i = 0; i < 4; i++)
7511
+ {
7512
+ for (int j = 0; j < 4; j++)
7513
+ {
7514
+ tmp[j] = b[j + i * 4];
7515
+ }
7516
+ vec4_dot_fp64(a, tmp, out_val[i]);
7517
+ }
7518
+ }
7519
+ `
7520
+ );
7785
7521
 
7786
- PBRInfo pbrInfo = PBRInfo(
7787
- 0.0, // NdotL
7788
- NdotV,
7789
- 0.0, // NdotH
7790
- 0.0, // LdotH
7791
- 0.0, // VdotH
7792
- perceptualRoughness,
7793
- metallic,
7794
- specularEnvironmentR0,
7795
- specularEnvironmentR90,
7796
- alphaRoughness,
7797
- diffuseColor,
7798
- specularColor,
7799
- n,
7800
- v
7801
- );
7522
+ // src/modules/math/fp64/fp64.ts
7523
+ var defaultUniforms = {
7524
+ // Used in LUMA_FP64_CODE_ELIMINATION_WORKAROUND
7525
+ ONE: 1
7526
+ };
7527
+ var fp64arithmetic = {
7528
+ name: "fp64arithmetic",
7529
+ vs: fp64arithmeticShader,
7530
+ defaultUniforms,
7531
+ uniformTypes: { ONE: "f32" },
7532
+ // Additional Functions
7533
+ fp64ify,
7534
+ fp64LowPart,
7535
+ fp64ifyMatrix4
7536
+ };
7537
+ var fp64 = {
7538
+ name: "fp64",
7539
+ vs: fp64functionShader,
7540
+ dependencies: [fp64arithmetic],
7541
+ // Additional Functions
7542
+ fp64ify,
7543
+ fp64LowPart,
7544
+ fp64ifyMatrix4
7545
+ };
7802
7546
 
7547
+ // src/modules/engine/picking/picking.ts
7548
+ var DEFAULT_HIGHLIGHT_COLOR = [0, 1, 1, 1];
7549
+ var vs = (
7550
+ /* glsl */
7551
+ `uniform pickingUniforms {
7552
+ float isActive;
7553
+ float isAttribute;
7554
+ float isHighlightActive;
7555
+ float useFloatColors;
7556
+ vec3 highlightedObjectColor;
7557
+ vec4 highlightColor;
7558
+ } picking;
7803
7559
 
7804
- #ifdef USE_LIGHTS
7805
- // Apply ambient light
7806
- PBRInfo_setAmbientLight(pbrInfo);
7807
- color += calculateFinalColor(pbrInfo, lighting.ambientColor);
7560
+ out vec4 picking_vRGBcolor_Avalid;
7808
7561
 
7809
- // Apply directional light
7810
- for(int i = 0; i < lighting.directionalLightCount; i++) {
7811
- if (i < lighting.directionalLightCount) {
7812
- PBRInfo_setDirectionalLight(pbrInfo, lighting_getDirectionalLight(i).direction);
7813
- color += calculateFinalColor(pbrInfo, lighting_getDirectionalLight(i).color);
7814
- }
7815
- }
7562
+ // Normalize unsigned byte color to 0-1 range
7563
+ vec3 picking_normalizeColor(vec3 color) {
7564
+ return picking.useFloatColors > 0.5 ? color : color / 255.0;
7565
+ }
7816
7566
 
7817
- // Apply point light
7818
- for(int i = 0; i < lighting.pointLightCount; i++) {
7819
- if (i < lighting.pointLightCount) {
7820
- PBRInfo_setPointLight(pbrInfo, lighting_getPointLight(i));
7821
- float attenuation = getPointLightAttenuation(lighting_getPointLight(i), distance(lighting_getPointLight(i).position, pbr_vPosition));
7822
- color += calculateFinalColor(pbrInfo, lighting_getPointLight(i).color / attenuation);
7823
- }
7824
- }
7825
- #endif
7567
+ // Normalize unsigned byte color to 0-1 range
7568
+ vec4 picking_normalizeColor(vec4 color) {
7569
+ return picking.useFloatColors > 0.5 ? color : color / 255.0;
7570
+ }
7826
7571
 
7827
- // Calculate lighting contribution from image based lighting source (IBL)
7828
- #ifdef USE_IBL
7829
- if (pbrMaterial.IBLenabled) {
7830
- color += getIBLContribution(pbrInfo, n, reflection);
7831
- }
7832
- #endif
7572
+ bool picking_isColorZero(vec3 color) {
7573
+ return dot(color, vec3(1.0)) < 0.00001;
7574
+ }
7833
7575
 
7834
- // Apply optional PBR terms for additional (optional) shading
7835
- #ifdef HAS_OCCLUSIONMAP
7836
- if (pbrMaterial.occlusionMapEnabled) {
7837
- float ao = texture(pbr_occlusionSampler, pbr_vUV).r;
7838
- color = mix(color, color * ao, pbrMaterial.occlusionStrength);
7839
- }
7840
- #endif
7576
+ bool picking_isColorValid(vec3 color) {
7577
+ return dot(color, vec3(1.0)) > 0.00001;
7578
+ }
7841
7579
 
7842
- #ifdef HAS_EMISSIVEMAP
7843
- if (pbrMaterial.emissiveMapEnabled) {
7844
- vec3 emissive = SRGBtoLINEAR(texture(pbr_emissiveSampler, pbr_vUV)).rgb * pbrMaterial.emissiveFactor;
7845
- color += emissive;
7846
- }
7847
- #endif
7580
+ // Check if this vertex is highlighted
7581
+ bool isVertexHighlighted(vec3 vertexColor) {
7582
+ vec3 highlightedObjectColor = picking_normalizeColor(picking.highlightedObjectColor);
7583
+ return
7584
+ bool(picking.isHighlightActive) && picking_isColorZero(abs(vertexColor - highlightedObjectColor));
7585
+ }
7848
7586
 
7849
- // This section uses mix to override final color for reference app visualization
7850
- // of various parameters in the lighting equation.
7851
- #ifdef PBR_DEBUG
7852
- // TODO: Figure out how to debug multiple lights
7587
+ // Set the current picking color
7588
+ void picking_setPickingColor(vec3 pickingColor) {
7589
+ pickingColor = picking_normalizeColor(pickingColor);
7853
7590
 
7854
- // color = mix(color, F, pbr_scaleFGDSpec.x);
7855
- // color = mix(color, vec3(G), pbr_scaleFGDSpec.y);
7856
- // color = mix(color, vec3(D), pbr_scaleFGDSpec.z);
7857
- // color = mix(color, specContrib, pbr_scaleFGDSpec.w);
7591
+ if (bool(picking.isActive)) {
7592
+ // Use alpha as the validity flag. If pickingColor is [0, 0, 0] fragment is non-pickable
7593
+ picking_vRGBcolor_Avalid.a = float(picking_isColorValid(pickingColor));
7858
7594
 
7859
- // color = mix(color, diffuseContrib, pbr_scaleDiffBaseMR.x);
7860
- color = mix(color, baseColor.rgb, pbrMaterial.scaleDiffBaseMR.y);
7861
- color = mix(color, vec3(metallic), pbrMaterial.scaleDiffBaseMR.z);
7862
- color = mix(color, vec3(perceptualRoughness), pbrMaterial.scaleDiffBaseMR.w);
7863
- #endif
7595
+ if (!bool(picking.isAttribute)) {
7596
+ // Stores the picking color so that the fragment shader can render it during picking
7597
+ picking_vRGBcolor_Avalid.rgb = pickingColor;
7598
+ }
7599
+ } else {
7600
+ // Do the comparison with selected item color in vertex shader as it should mean fewer compares
7601
+ picking_vRGBcolor_Avalid.a = float(isVertexHighlighted(pickingColor));
7602
+ }
7603
+ }
7864
7604
 
7605
+ void picking_setPickingAttribute(float value) {
7606
+ if (bool(picking.isAttribute)) {
7607
+ picking_vRGBcolor_Avalid.r = value;
7865
7608
  }
7609
+ }
7866
7610
 
7867
- return vec4(pow(color,vec3(1.0/2.2)), baseColor.a);
7611
+ void picking_setPickingAttribute(vec2 value) {
7612
+ if (bool(picking.isAttribute)) {
7613
+ picking_vRGBcolor_Avalid.rg = value;
7614
+ }
7868
7615
  }
7869
- `
7870
- );
7871
7616
 
7872
- // src/modules/lighting/pbr-material/pbr-projection.ts
7873
- var uniformBlock = (
7874
- /* glsl */
7875
- `uniform pbrProjectionUniforms {
7876
- mat4 modelViewProjectionMatrix;
7877
- mat4 modelMatrix;
7878
- mat4 normalMatrix;
7879
- vec3 camera;
7880
- } pbrProjection;
7617
+ void picking_setPickingAttribute(vec3 value) {
7618
+ if (bool(picking.isAttribute)) {
7619
+ picking_vRGBcolor_Avalid.rgb = value;
7620
+ }
7621
+ }
7881
7622
  `
7882
7623
  );
7883
- var pbrProjection = {
7884
- name: "pbrProjection",
7885
- vs: uniformBlock,
7886
- fs: uniformBlock,
7887
- // TODO why is this needed?
7888
- getUniforms: (props) => props,
7889
- uniformTypes: {
7890
- modelViewProjectionMatrix: "mat4x4<f32>",
7891
- modelMatrix: "mat4x4<f32>",
7892
- normalMatrix: "mat4x4<f32>",
7893
- camera: "vec3<i32>"
7624
+ var fs2 = (
7625
+ /* glsl */
7626
+ `uniform pickingUniforms {
7627
+ float isActive;
7628
+ float isAttribute;
7629
+ float isHighlightActive;
7630
+ float useFloatColors;
7631
+ vec3 highlightedObjectColor;
7632
+ vec4 highlightColor;
7633
+ } picking;
7634
+
7635
+ in vec4 picking_vRGBcolor_Avalid;
7636
+
7637
+ /*
7638
+ * Returns highlight color if this item is selected.
7639
+ */
7640
+ vec4 picking_filterHighlightColor(vec4 color) {
7641
+ // If we are still picking, we don't highlight
7642
+ if (picking.isActive > 0.5) {
7643
+ return color;
7644
+ }
7645
+
7646
+ bool selected = bool(picking_vRGBcolor_Avalid.a);
7647
+
7648
+ if (selected) {
7649
+ // Blend in highlight color based on its alpha value
7650
+ float highLightAlpha = picking.highlightColor.a;
7651
+ float blendedAlpha = highLightAlpha + color.a * (1.0 - highLightAlpha);
7652
+ float highLightRatio = highLightAlpha / blendedAlpha;
7653
+
7654
+ vec3 blendedRGB = mix(color.rgb, picking.highlightColor.rgb, highLightRatio);
7655
+ return vec4(blendedRGB, blendedAlpha);
7656
+ } else {
7657
+ return color;
7658
+ }
7659
+ }
7660
+
7661
+ /*
7662
+ * Returns picking color if picking enabled else unmodified argument.
7663
+ */
7664
+ vec4 picking_filterPickingColor(vec4 color) {
7665
+ if (bool(picking.isActive)) {
7666
+ if (picking_vRGBcolor_Avalid.a == 0.0) {
7667
+ discard;
7894
7668
  }
7895
- };
7669
+ return picking_vRGBcolor_Avalid;
7670
+ }
7671
+ return color;
7672
+ }
7896
7673
 
7897
- // src/modules/lighting/pbr-material/pbr-material.ts
7898
- var pbrMaterial = {
7674
+ /*
7675
+ * Returns picking color if picking is enabled if not
7676
+ * highlight color if this item is selected, otherwise unmodified argument.
7677
+ */
7678
+ vec4 picking_filterColor(vec4 color) {
7679
+ vec4 highlightColor = picking_filterHighlightColor(color);
7680
+ return picking_filterPickingColor(highlightColor);
7681
+ }
7682
+ `
7683
+ );
7684
+ var picking = {
7899
7685
  props: {},
7900
7686
  uniforms: {},
7901
- name: "pbrMaterial",
7902
- dependencies: [lighting, pbrProjection],
7903
- vs: vs2,
7904
- fs: fs3,
7905
- defines: {
7906
- LIGHTING_FRAGMENT: 1
7907
- // TODO defining these as 0 breaks shader
7908
- // HAS_NORMALMAP: 0
7909
- // HAS_EMISSIVEMAP: 0,
7910
- // HAS_OCCLUSIONMAP: 0,
7911
- // HAS_BASECOLORMAP: 0,
7912
- // HAS_METALROUGHNESSMAP: 0,
7913
- // ALPHA_CUTOFF: 0
7914
- // USE_IBL: 0
7915
- // PBR_DEBUG: 0
7916
- },
7917
- getUniforms: (props) => props,
7687
+ name: "picking",
7918
7688
  uniformTypes: {
7919
- // Material is unlit
7920
- unlit: "i32",
7921
- // Base color map
7922
- baseColorMapEnabled: "i32",
7923
- baseColorFactor: "vec4<f32>",
7924
- normalMapEnabled: "i32",
7925
- normalScale: "f32",
7926
- // #ifdef HAS_NORMALMAP
7927
- emissiveMapEnabled: "i32",
7928
- emissiveFactor: "vec3<f32>",
7929
- // #ifdef HAS_EMISSIVEMAP
7930
- metallicRoughnessValues: "vec2<f32>",
7931
- metallicRoughnessMapEnabled: "i32",
7932
- occlusionMapEnabled: "i32",
7933
- occlusionStrength: "f32",
7934
- // #ifdef HAS_OCCLUSIONMAP
7935
- alphaCutoffEnabled: "i32",
7936
- alphaCutoff: "f32",
7937
- // #ifdef ALPHA_CUTOFF
7938
- // IBL
7939
- IBLenabled: "i32",
7940
- scaleIBLAmbient: "vec2<f32>",
7941
- // #ifdef USE_IBL
7942
- // debugging flags used for shader output of intermediate PBR variables
7943
- // #ifdef PBR_DEBUG
7944
- scaleDiffBaseMR: "vec4<f32>",
7945
- scaleFGDSpec: "vec4<f32>"
7946
- }
7689
+ isActive: "f32",
7690
+ isAttribute: "f32",
7691
+ isHighlightActive: "f32",
7692
+ useFloatColors: "f32",
7693
+ highlightedObjectColor: "vec3<f32>",
7694
+ highlightColor: "vec4<f32>"
7695
+ },
7696
+ defaultUniforms: {
7697
+ isActive: false,
7698
+ isAttribute: false,
7699
+ isHighlightActive: false,
7700
+ useFloatColors: true,
7701
+ highlightedObjectColor: [0, 0, 0],
7702
+ highlightColor: DEFAULT_HIGHLIGHT_COLOR
7703
+ },
7704
+ vs,
7705
+ fs: fs2,
7706
+ getUniforms
7947
7707
  };
7708
+ function getUniforms(opts = {}, prevUniforms) {
7709
+ const uniforms = {};
7710
+ if (opts.highlightedObjectColor === void 0) {
7711
+ } else if (opts.highlightedObjectColor === null) {
7712
+ uniforms.isHighlightActive = false;
7713
+ } else {
7714
+ uniforms.isHighlightActive = true;
7715
+ const highlightedObjectColor = opts.highlightedObjectColor.slice(0, 3);
7716
+ uniforms.highlightedObjectColor = highlightedObjectColor;
7717
+ }
7718
+ if (opts.highlightColor) {
7719
+ const color = Array.from(opts.highlightColor, (x) => x / 255);
7720
+ if (!Number.isFinite(color[3])) {
7721
+ color[3] = 1;
7722
+ }
7723
+ uniforms.highlightColor = color;
7724
+ }
7725
+ if (opts.isActive !== void 0) {
7726
+ uniforms.isActive = Boolean(opts.isActive);
7727
+ uniforms.isAttribute = Boolean(opts.isAttribute);
7728
+ }
7729
+ if (opts.useFloatColors !== void 0) {
7730
+ uniforms.useFloatColors = Boolean(opts.useFloatColors);
7731
+ }
7732
+ return uniforms;
7733
+ }
7948
7734
 
7949
- // src/modules-webgl1/math/fp64/fp64-arithmetic-glsl.ts
7950
- var fp64arithmeticShader = (
7735
+ // src/modules/lighting/lights/lighting.ts
7736
+ var import_core3 = __toESM(require_core(), 1);
7737
+
7738
+ // src/modules/lighting/lights/lighting-uniforms-glsl.ts
7739
+ var lightingUniformsGLSL = (
7951
7740
  /* glsl */
7952
- `uniform float ONE;
7741
+ `precision highp int;
7953
7742
 
7954
- /*
7955
- About LUMA_FP64_CODE_ELIMINATION_WORKAROUND
7743
+ // #if (defined(SHADER_TYPE_FRAGMENT) && defined(LIGHTING_FRAGMENT)) || (defined(SHADER_TYPE_VERTEX) && defined(LIGHTING_VERTEX))
7744
+ struct AmbientLight {
7745
+ vec3 color;
7746
+ };
7956
7747
 
7957
- The purpose of this workaround is to prevent shader compilers from
7958
- optimizing away necessary arithmetic operations by swapping their sequences
7959
- or transform the equation to some 'equivalent' form.
7748
+ struct PointLight {
7749
+ vec3 color;
7750
+ vec3 position;
7751
+ vec3 attenuation; // 2nd order x:Constant-y:Linear-z:Exponential
7752
+ };
7960
7753
 
7961
- The method is to multiply an artifical variable, ONE, which will be known to
7962
- the compiler to be 1 only at runtime. The whole expression is then represented
7963
- as a polynomial with respective to ONE. In the coefficients of all terms, only one a
7964
- and one b should appear
7754
+ struct DirectionalLight {
7755
+ vec3 color;
7756
+ vec3 direction;
7757
+ };
7965
7758
 
7966
- err = (a + b) * ONE^6 - a * ONE^5 - (a + b) * ONE^4 + a * ONE^3 - b - (a + b) * ONE^2 + a * ONE
7967
- */
7759
+ uniform lightingUniforms {
7760
+ int enabled;
7761
+ int lightType;
7968
7762
 
7969
- // Divide float number to high and low floats to extend fraction bits
7970
- vec2 split(float a) {
7971
- const float SPLIT = 4097.0;
7972
- float t = a * SPLIT;
7973
- #if defined(LUMA_FP64_CODE_ELIMINATION_WORKAROUND)
7974
- float a_hi = t * ONE - (t - a);
7975
- float a_lo = a * ONE - a_hi;
7976
- #else
7977
- float a_hi = t - (t - a);
7978
- float a_lo = a - a_hi;
7979
- #endif
7980
- return vec2(a_hi, a_lo);
7981
- }
7763
+ int directionalLightCount;
7764
+ int pointLightCount;
7982
7765
 
7983
- // Divide float number again when high float uses too many fraction bits
7984
- vec2 split2(vec2 a) {
7985
- vec2 b = split(a.x);
7986
- b.y += a.y;
7987
- return b;
7988
- }
7766
+ vec3 ambientColor;
7989
7767
 
7990
- // Special sum operation when a > b
7991
- vec2 quickTwoSum(float a, float b) {
7992
- #if defined(LUMA_FP64_CODE_ELIMINATION_WORKAROUND)
7993
- float sum = (a + b) * ONE;
7994
- float err = b - (sum - a) * ONE;
7995
- #else
7996
- float sum = a + b;
7997
- float err = b - (sum - a);
7998
- #endif
7999
- return vec2(sum, err);
8000
- }
7768
+ vec3 lightColor0;
7769
+ vec3 lightPosition0;
7770
+ vec3 lightDirection0;
7771
+ vec3 lightAttenuation0;
8001
7772
 
8002
- // General sum operation
8003
- vec2 twoSum(float a, float b) {
8004
- float s = (a + b);
8005
- #if defined(LUMA_FP64_CODE_ELIMINATION_WORKAROUND)
8006
- float v = (s * ONE - a) * ONE;
8007
- float err = (a - (s - v) * ONE) * ONE * ONE * ONE + (b - v);
8008
- #else
8009
- float v = s - a;
8010
- float err = (a - (s - v)) + (b - v);
8011
- #endif
8012
- return vec2(s, err);
8013
- }
7773
+ vec3 lightColor1;
7774
+ vec3 lightPosition1;
7775
+ vec3 lightDirection1;
7776
+ vec3 lightAttenuation1;
8014
7777
 
8015
- vec2 twoSub(float a, float b) {
8016
- float s = (a - b);
8017
- #if defined(LUMA_FP64_CODE_ELIMINATION_WORKAROUND)
8018
- float v = (s * ONE - a) * ONE;
8019
- float err = (a - (s - v) * ONE) * ONE * ONE * ONE - (b + v);
8020
- #else
8021
- float v = s - a;
8022
- float err = (a - (s - v)) - (b + v);
8023
- #endif
8024
- return vec2(s, err);
8025
- }
7778
+ vec3 lightColor2;
7779
+ vec3 lightPosition2;
7780
+ vec3 lightDirection2;
7781
+ vec3 lightAttenuation2;
7782
+ } lighting;
8026
7783
 
8027
- vec2 twoSqr(float a) {
8028
- float prod = a * a;
8029
- vec2 a_fp64 = split(a);
8030
- #if defined(LUMA_FP64_CODE_ELIMINATION_WORKAROUND)
8031
- float err = ((a_fp64.x * a_fp64.x - prod) * ONE + 2.0 * a_fp64.x *
8032
- a_fp64.y * ONE * ONE) + a_fp64.y * a_fp64.y * ONE * ONE * ONE;
8033
- #else
8034
- float err = ((a_fp64.x * a_fp64.x - prod) + 2.0 * a_fp64.x * a_fp64.y) + a_fp64.y * a_fp64.y;
8035
- #endif
8036
- return vec2(prod, err);
8037
- }
8038
-
8039
- vec2 twoProd(float a, float b) {
8040
- float prod = a * b;
8041
- vec2 a_fp64 = split(a);
8042
- vec2 b_fp64 = split(b);
8043
- float err = ((a_fp64.x * b_fp64.x - prod) + a_fp64.x * b_fp64.y +
8044
- a_fp64.y * b_fp64.x) + a_fp64.y * b_fp64.y;
8045
- return vec2(prod, err);
8046
- }
8047
-
8048
- vec2 sum_fp64(vec2 a, vec2 b) {
8049
- vec2 s, t;
8050
- s = twoSum(a.x, b.x);
8051
- t = twoSum(a.y, b.y);
8052
- s.y += t.x;
8053
- s = quickTwoSum(s.x, s.y);
8054
- s.y += t.y;
8055
- s = quickTwoSum(s.x, s.y);
8056
- return s;
8057
- }
8058
-
8059
- vec2 sub_fp64(vec2 a, vec2 b) {
8060
- vec2 s, t;
8061
- s = twoSub(a.x, b.x);
8062
- t = twoSub(a.y, b.y);
8063
- s.y += t.x;
8064
- s = quickTwoSum(s.x, s.y);
8065
- s.y += t.y;
8066
- s = quickTwoSum(s.x, s.y);
8067
- return s;
7784
+ PointLight lighting_getPointLight(int index) {
7785
+ switch (index) {
7786
+ case 0:
7787
+ return PointLight(lighting.lightColor0, lighting.lightPosition0, lighting.lightAttenuation0);
7788
+ case 1:
7789
+ return PointLight(lighting.lightColor1, lighting.lightPosition1, lighting.lightAttenuation1);
7790
+ case 2:
7791
+ default:
7792
+ return PointLight(lighting.lightColor2, lighting.lightPosition2, lighting.lightAttenuation2);
7793
+ }
8068
7794
  }
8069
7795
 
8070
- vec2 mul_fp64(vec2 a, vec2 b) {
8071
- vec2 prod = twoProd(a.x, b.x);
8072
- // y component is for the error
8073
- prod.y += a.x * b.y;
8074
- #if defined(LUMA_FP64_HIGH_BITS_OVERFLOW_WORKAROUND)
8075
- prod = split2(prod);
8076
- #endif
8077
- prod = quickTwoSum(prod.x, prod.y);
8078
- prod.y += a.y * b.x;
8079
- #if defined(LUMA_FP64_HIGH_BITS_OVERFLOW_WORKAROUND)
8080
- prod = split2(prod);
8081
- #endif
8082
- prod = quickTwoSum(prod.x, prod.y);
8083
- return prod;
8084
- }
7796
+ DirectionalLight lighting_getDirectionalLight(int index) {
7797
+ switch (index) {
7798
+ case 0:
7799
+ return DirectionalLight(lighting.lightColor0, lighting.lightDirection0);
7800
+ case 1:
7801
+ return DirectionalLight(lighting.lightColor1, lighting.lightDirection1);
7802
+ case 2:
7803
+ default:
7804
+ return DirectionalLight(lighting.lightColor2, lighting.lightDirection2);
7805
+ }
7806
+ }
8085
7807
 
8086
- vec2 div_fp64(vec2 a, vec2 b) {
8087
- float xn = 1.0 / b.x;
8088
- #if defined(LUMA_FP64_HIGH_BITS_OVERFLOW_WORKAROUND)
8089
- vec2 yn = mul_fp64(a, vec2(xn, 0));
8090
- #else
8091
- vec2 yn = a * xn;
8092
- #endif
8093
- float diff = (sub_fp64(a, mul_fp64(b, yn))).x;
8094
- vec2 prod = twoProd(xn, diff);
8095
- return sum_fp64(yn, prod);
7808
+ float getPointLightAttenuation(PointLight pointLight, float distance) {
7809
+ return pointLight.attenuation.x
7810
+ + pointLight.attenuation.y * distance
7811
+ + pointLight.attenuation.z * distance * distance;
8096
7812
  }
8097
7813
 
8098
- vec2 sqrt_fp64(vec2 a) {
8099
- if (a.x == 0.0 && a.y == 0.0) return vec2(0.0, 0.0);
8100
- if (a.x < 0.0) return vec2(0.0 / 0.0, 0.0 / 0.0);
8101
-
8102
- float x = 1.0 / sqrt(a.x);
8103
- float yn = a.x * x;
8104
- #if defined(LUMA_FP64_CODE_ELIMINATION_WORKAROUND)
8105
- vec2 yn_sqr = twoSqr(yn) * ONE;
8106
- #else
8107
- vec2 yn_sqr = twoSqr(yn);
8108
- #endif
8109
- float diff = sub_fp64(a, yn_sqr).x;
8110
- vec2 prod = twoProd(x * 0.5, diff);
8111
- #if defined(LUMA_FP64_HIGH_BITS_OVERFLOW_WORKAROUND)
8112
- return sum_fp64(split(yn), prod);
8113
- #else
8114
- return sum_fp64(vec2(yn, 0.0), prod);
8115
- #endif
8116
- }
7814
+ // #endif
8117
7815
  `
8118
7816
  );
8119
7817
 
8120
- // src/modules-webgl1/math/fp64/fp64-functions-glsl.ts
8121
- var fp64functionShader = (
8122
- /* glsl */
8123
- `const vec2 E_FP64 = vec2(2.7182817459106445e+00, 8.254840366817007e-08);
8124
- const vec2 LOG2_FP64 = vec2(0.6931471824645996e+00, -1.9046542121259336e-09);
8125
- const vec2 PI_FP64 = vec2(3.1415927410125732, -8.742278012618954e-8);
8126
- const vec2 TWO_PI_FP64 = vec2(6.2831854820251465, -1.7484556025237907e-7);
8127
- const vec2 PI_2_FP64 = vec2(1.5707963705062866, -4.371139006309477e-8);
8128
- const vec2 PI_4_FP64 = vec2(0.7853981852531433, -2.1855695031547384e-8);
8129
- const vec2 PI_16_FP64 = vec2(0.19634954631328583, -5.463923757886846e-9);
8130
- const vec2 PI_16_2_FP64 = vec2(0.39269909262657166, -1.0927847515773692e-8);
8131
- const vec2 PI_16_3_FP64 = vec2(0.5890486240386963, -1.4906100798128818e-9);
8132
- const vec2 PI_180_FP64 = vec2(0.01745329238474369, 1.3519960498364902e-10);
8133
-
8134
- const vec2 SIN_TABLE_0_FP64 = vec2(0.19509032368659973, -1.6704714833615242e-9);
8135
- const vec2 SIN_TABLE_1_FP64 = vec2(0.3826834261417389, 6.22335089017767e-9);
8136
- const vec2 SIN_TABLE_2_FP64 = vec2(0.5555702447891235, -1.1769521357507529e-8);
8137
- const vec2 SIN_TABLE_3_FP64 = vec2(0.7071067690849304, 1.2101617041793133e-8);
8138
-
8139
- const vec2 COS_TABLE_0_FP64 = vec2(0.9807852506637573, 2.9739473106360492e-8);
8140
- const vec2 COS_TABLE_1_FP64 = vec2(0.9238795042037964, 2.8307490351764386e-8);
8141
- const vec2 COS_TABLE_2_FP64 = vec2(0.8314695954322815, 1.6870263741530778e-8);
8142
- const vec2 COS_TABLE_3_FP64 = vec2(0.7071067690849304, 1.2101617152815436e-8);
8143
-
8144
- const vec2 INVERSE_FACTORIAL_3_FP64 = vec2(1.666666716337204e-01, -4.967053879312289e-09); // 1/3!
8145
- const vec2 INVERSE_FACTORIAL_4_FP64 = vec2(4.16666679084301e-02, -1.2417634698280722e-09); // 1/4!
8146
- const vec2 INVERSE_FACTORIAL_5_FP64 = vec2(8.333333767950535e-03, -4.34617203337595e-10); // 1/5!
8147
- const vec2 INVERSE_FACTORIAL_6_FP64 = vec2(1.3888889225199819e-03, -3.3631094437103215e-11); // 1/6!
8148
- const vec2 INVERSE_FACTORIAL_7_FP64 = vec2(1.9841270113829523e-04, -2.725596874933456e-12); // 1/7!
8149
- const vec2 INVERSE_FACTORIAL_8_FP64 = vec2(2.4801587642286904e-05, -3.406996025904184e-13); // 1/8!
8150
- const vec2 INVERSE_FACTORIAL_9_FP64 = vec2(2.75573188446287533e-06, 3.7935713937038186e-14); // 1/9!
8151
- const vec2 INVERSE_FACTORIAL_10_FP64 = vec2(2.755731998149713e-07, -7.575112367869873e-15); // 1/10!
8152
-
8153
- float nint(float d) {
8154
- if (d == floor(d)) return d;
8155
- return floor(d + 0.5);
8156
- }
8157
-
8158
- vec2 nint_fp64(vec2 a) {
8159
- float hi = nint(a.x);
8160
- float lo;
8161
- vec2 tmp;
8162
- if (hi == a.x) {
8163
- lo = nint(a.y);
8164
- tmp = quickTwoSum(hi, lo);
8165
- } else {
8166
- lo = 0.0;
8167
- if (abs(hi - a.x) == 0.5 && a.y < 0.0) {
8168
- hi -= 1.0;
8169
- }
8170
- tmp = vec2(hi, lo);
8171
- }
8172
- return tmp;
8173
- }
8174
-
8175
- /* k_power controls how much range reduction we would like to have
8176
- Range reduction uses the following method:
8177
- assume a = k_power * r + m * log(2), k and m being integers.
8178
- Set k_power = 4 (we can choose other k to trade accuracy with performance.
8179
- we only need to calculate exp(r) and using exp(a) = 2^m * exp(r)^k_power;
8180
- */
8181
-
8182
- vec2 exp_fp64(vec2 a) {
8183
- // We need to make sure these two numbers match
8184
- // as bit-wise shift is not available in GLSL 1.0
8185
- const int k_power = 4;
8186
- const float k = 16.0;
8187
-
8188
- const float inv_k = 1.0 / k;
8189
-
8190
- if (a.x <= -88.0) return vec2(0.0, 0.0);
8191
- if (a.x >= 88.0) return vec2(1.0 / 0.0, 1.0 / 0.0);
8192
- if (a.x == 0.0 && a.y == 0.0) return vec2(1.0, 0.0);
8193
- if (a.x == 1.0 && a.y == 0.0) return E_FP64;
8194
-
8195
- float m = floor(a.x / LOG2_FP64.x + 0.5);
8196
- vec2 r = sub_fp64(a, mul_fp64(LOG2_FP64, vec2(m, 0.0))) * inv_k;
8197
- vec2 s, t, p;
7818
+ // src/modules/lighting/lights/lighting-uniforms-wgsl.ts
7819
+ var lightingUniformsWGSL = (
7820
+ /* wgsl */
7821
+ `// #if (defined(SHADER_TYPE_FRAGMENT) && defined(LIGHTING_FRAGMENT)) || (defined(SHADER_TYPE_VERTEX) && defined(LIGHTING_VERTEX))
7822
+ struct AmbientLight {
7823
+ color: vec3<f32>,
7824
+ };
8198
7825
 
8199
- p = mul_fp64(r, r);
8200
- s = sum_fp64(r, p * 0.5);
8201
- p = mul_fp64(p, r);
8202
- t = mul_fp64(p, INVERSE_FACTORIAL_3_FP64);
7826
+ struct PointLight {
7827
+ color: vec3<f32>,
7828
+ position: vec3<f32>,
7829
+ attenuation: vec3<f32>, // 2nd order x:Constant-y:Linear-z:Exponential
7830
+ };
8203
7831
 
8204
- s = sum_fp64(s, t);
8205
- p = mul_fp64(p, r);
8206
- t = mul_fp64(p, INVERSE_FACTORIAL_4_FP64);
7832
+ struct DirectionalLight {
7833
+ color: vec3<f32>,
7834
+ direction: vec3<f32>,
7835
+ };
8207
7836
 
8208
- s = sum_fp64(s, t);
8209
- p = mul_fp64(p, r);
8210
- t = mul_fp64(p, INVERSE_FACTORIAL_5_FP64);
7837
+ struct lightingUniforms {
7838
+ enabled: i32,
7839
+ poightCount: i32,
7840
+ directionalLightCount: i32,
8211
7841
 
8212
- // s = sum_fp64(s, t);
8213
- // p = mul_fp64(p, r);
8214
- // t = mul_fp64(p, INVERSE_FACTORIAL_6_FP64);
7842
+ ambientColor: vec3<f32>,
8215
7843
 
8216
- // s = sum_fp64(s, t);
8217
- // p = mul_fp64(p, r);
8218
- // t = mul_fp64(p, INVERSE_FACTORIAL_7_FP64);
7844
+ // TODO - support multiple lights by uncommenting arrays below
7845
+ lightType: i32,
7846
+ lightColor: vec3<f32>,
7847
+ lightDirection: vec3<f32>,
7848
+ lightPosition: vec3<f32>,
7849
+ lightAttenuation: vec3<f32>,
8219
7850
 
8220
- s = sum_fp64(s, t);
7851
+ // AmbientLight ambientLight;
7852
+ // PointLight pointLight[MAX_LIGHTS];
7853
+ // DirectionalLight directionalLight[MAX_LIGHTS];
7854
+ };
8221
7855
 
7856
+ // Binding 0:1 is reserved for lighting (Note: could go into separate bind group as it is stable across draw calls)
7857
+ @binding(1) @group(0) var<uniform> lighting : lightingUniforms;
8222
7858
 
8223
- // At this point, s = exp(r) - 1; but after following 4 recursions, we will get exp(r) ^ 512 - 1.
8224
- for (int i = 0; i < k_power; i++) {
8225
- s = sum_fp64(s * 2.0, mul_fp64(s, s));
8226
- }
7859
+ fn lighting_getPointLight(index: i32) -> PointLight {
7860
+ return PointLight(lighting.lightColor, lighting.lightPosition, lighting.lightAttenuation);
7861
+ }
8227
7862
 
8228
- #if defined(NVIDIA_FP64_WORKAROUND) || defined(INTEL_FP64_WORKAROUND)
8229
- s = sum_fp64(s, vec2(ONE, 0.0));
8230
- #else
8231
- s = sum_fp64(s, vec2(1.0, 0.0));
8232
- #endif
7863
+ fn lighting_getDirectionalLight(index: i32) -> DirectionalLight {
7864
+ return DirectionalLight(lighting.lightColor, lighting.lightDirection);
7865
+ }
8233
7866
 
8234
- return s * pow(2.0, m);
8235
- // return r;
7867
+ fn getPointLightAttenuation(pointLight: PointLight, distance: f32) -> f32 {
7868
+ return pointLight.attenuation.x
7869
+ + pointLight.attenuation.y * distance
7870
+ + pointLight.attenuation.z * distance * distance;
8236
7871
  }
7872
+ `
7873
+ );
8237
7874
 
8238
- vec2 log_fp64(vec2 a)
8239
- {
8240
- if (a.x == 1.0 && a.y == 0.0) return vec2(0.0, 0.0);
8241
- if (a.x <= 0.0) return vec2(0.0 / 0.0, 0.0 / 0.0);
8242
- vec2 x = vec2(log(a.x), 0.0);
8243
- vec2 s;
8244
- #if defined(NVIDIA_FP64_WORKAROUND) || defined(INTEL_FP64_WORKAROUND)
8245
- s = vec2(ONE, 0.0);
8246
- #else
8247
- s = vec2(1.0, 0.0);
8248
- #endif
8249
-
8250
- x = sub_fp64(sum_fp64(x, mul_fp64(a, exp_fp64(-x))), s);
8251
- return x;
8252
- }
8253
-
8254
- vec2 sin_taylor_fp64(vec2 a) {
8255
- vec2 r, s, t, x;
8256
-
8257
- if (a.x == 0.0 && a.y == 0.0) {
8258
- return vec2(0.0, 0.0);
7875
+ // src/modules/lighting/lights/lighting.ts
7876
+ var MAX_LIGHTS = 3;
7877
+ var COLOR_FACTOR = 255;
7878
+ var lighting = {
7879
+ props: {},
7880
+ uniforms: {},
7881
+ name: "lighting",
7882
+ defines: {
7883
+ MAX_LIGHTS
7884
+ },
7885
+ uniformTypes: {
7886
+ enabled: "i32",
7887
+ lightType: "i32",
7888
+ directionalLightCount: "i32",
7889
+ pointLightCount: "i32",
7890
+ ambientLightColor: "vec3<f32>",
7891
+ // TODO define as arrays once we have appropriate uniformTypes
7892
+ lightColor0: "vec3<f32>",
7893
+ lightPosition0: "vec3<f32>",
7894
+ // TODO - could combine direction and attenuation
7895
+ lightDirection0: "vec3<f32>",
7896
+ lightAttenuation0: "vec3<f32>",
7897
+ lightColor1: "vec3<f32>",
7898
+ lightPosition1: "vec3<f32>",
7899
+ lightDirection1: "vec3<f32>",
7900
+ lightAttenuation1: "vec3<f32>",
7901
+ lightColor2: "vec3<f32>",
7902
+ lightPosition2: "vec3<f32>",
7903
+ lightDirection2: "vec3<f32>",
7904
+ lightAttenuation2: "vec3<f32>"
7905
+ },
7906
+ defaultUniforms: {
7907
+ enabled: 1,
7908
+ lightType: 0 /* POINT */,
7909
+ directionalLightCount: 0,
7910
+ pointLightCount: 0,
7911
+ ambientLightColor: [0.1, 0.1, 0.1],
7912
+ lightColor0: [1, 1, 1],
7913
+ lightPosition0: [1, 1, 2],
7914
+ // TODO - could combine direction and attenuation
7915
+ lightDirection0: [1, 1, 1],
7916
+ lightAttenuation0: [1, 0, 0],
7917
+ lightColor1: [1, 1, 1],
7918
+ lightPosition1: [1, 1, 2],
7919
+ lightDirection1: [1, 1, 1],
7920
+ lightAttenuation1: [1, 0, 0],
7921
+ lightColor2: [1, 1, 1],
7922
+ lightPosition2: [1, 1, 2],
7923
+ lightDirection2: [1, 1, 1],
7924
+ lightAttenuation2: [1, 0, 0]
7925
+ },
7926
+ source: lightingUniformsWGSL,
7927
+ vs: lightingUniformsGLSL,
7928
+ fs: lightingUniformsGLSL,
7929
+ getUniforms: getUniforms2
7930
+ };
7931
+ function getUniforms2(props, prevUniforms = {}) {
7932
+ props = props ? { ...props } : props;
7933
+ if (!props) {
7934
+ return { ...lighting.defaultUniforms };
7935
+ }
7936
+ if (props.lights) {
7937
+ props = { ...props, ...extractLightTypes(props.lights), lights: void 0 };
7938
+ }
7939
+ const { ambientLight, pointLights, directionalLights } = props || {};
7940
+ const hasLights = ambientLight || pointLights && pointLights.length > 0 || directionalLights && directionalLights.length > 0;
7941
+ if (!hasLights) {
7942
+ return { ...lighting.defaultUniforms, enabled: 0 };
7943
+ }
7944
+ const uniforms = {
7945
+ ...lighting.defaultUniforms,
7946
+ ...prevUniforms,
7947
+ ...getLightSourceUniforms({ ambientLight, pointLights, directionalLights })
7948
+ };
7949
+ if (props.enabled !== void 0) {
7950
+ uniforms.enabled = props.enabled ? 1 : 0;
7951
+ }
7952
+ return uniforms;
7953
+ }
7954
+ function getLightSourceUniforms({
7955
+ ambientLight,
7956
+ pointLights = [],
7957
+ directionalLights = []
7958
+ }) {
7959
+ const lightSourceUniforms = {};
7960
+ lightSourceUniforms.ambientLightColor = convertColor(ambientLight);
7961
+ let currentLight = 0;
7962
+ for (const pointLight of pointLights) {
7963
+ lightSourceUniforms.lightType = 0 /* POINT */;
7964
+ const i = currentLight;
7965
+ lightSourceUniforms[`lightColor${i}`] = convertColor(pointLight);
7966
+ lightSourceUniforms[`lightPosition${i}`] = pointLight.position;
7967
+ lightSourceUniforms[`lightAttenuation${i}`] = pointLight.attenuation || [1, 0, 0];
7968
+ currentLight++;
7969
+ }
7970
+ for (const directionalLight of directionalLights) {
7971
+ lightSourceUniforms.lightType = 1 /* DIRECTIONAL */;
7972
+ const i = currentLight;
7973
+ lightSourceUniforms[`lightColor${i}`] = convertColor(directionalLight);
7974
+ lightSourceUniforms[`lightDirection${i}`] = directionalLight.direction;
7975
+ currentLight++;
7976
+ }
7977
+ if (currentLight > MAX_LIGHTS) {
7978
+ import_core3.log.warn("MAX_LIGHTS exceeded")();
7979
+ }
7980
+ lightSourceUniforms.directionalLightCount = directionalLights.length;
7981
+ lightSourceUniforms.pointLightCount = pointLights.length;
7982
+ return lightSourceUniforms;
7983
+ }
7984
+ function extractLightTypes(lights2) {
7985
+ const lightSources = { pointLights: [], directionalLights: [] };
7986
+ for (const light of lights2 || []) {
7987
+ switch (light.type) {
7988
+ case "ambient":
7989
+ lightSources.ambientLight = light;
7990
+ break;
7991
+ case "directional":
7992
+ lightSources.directionalLights?.push(light);
7993
+ break;
7994
+ case "point":
7995
+ lightSources.pointLights?.push(light);
7996
+ break;
7997
+ default:
7998
+ }
7999
+ }
8000
+ return lightSources;
8001
+ }
8002
+ function convertColor(colorDef = {}) {
8003
+ const { color = [0, 0, 0], intensity = 1 } = colorDef;
8004
+ return color.map((component) => component * intensity / COLOR_FACTOR);
8259
8005
  }
8260
8006
 
8261
- x = -mul_fp64(a, a);
8262
- s = a;
8263
- r = a;
8007
+ // src/modules/lighting/no-material/dirlight.ts
8008
+ var SOURCE_WGSL = (
8009
+ /* WGSL */
8010
+ `
8011
+ struct dirlightUniforms {
8012
+ lightDirection: vec3<f32>,
8013
+ };
8264
8014
 
8265
- r = mul_fp64(r, x);
8266
- t = mul_fp64(r, INVERSE_FACTORIAL_3_FP64);
8267
- s = sum_fp64(s, t);
8015
+ alias DirlightNormal = vec3<f32>;
8268
8016
 
8269
- r = mul_fp64(r, x);
8270
- t = mul_fp64(r, INVERSE_FACTORIAL_5_FP64);
8271
- s = sum_fp64(s, t);
8017
+ struct DirlightInputs {
8018
+ normal: DirlightNormal,
8019
+ };
8272
8020
 
8273
- /* keep the following commented code in case we need them
8274
- for extra accuracy from the Taylor expansion*/
8021
+ @binding(1) @group(0) var<uniform> dirlight : dirlightUniforms;
8275
8022
 
8276
- // r = mul_fp64(r, x);
8277
- // t = mul_fp64(r, INVERSE_FACTORIAL_7_FP64);
8278
- // s = sum_fp64(s, t);
8023
+ // For vertex
8024
+ fn dirlight_setNormal(normal: vec3<f32>) -> DirlightNormal {
8025
+ return normalize(normal);
8026
+ }
8279
8027
 
8280
- // r = mul_fp64(r, x);
8281
- // t = mul_fp64(r, INVERSE_FACTORIAL_9_FP64);
8282
- // s = sum_fp64(s, t);
8028
+ // Returns color attenuated by angle from light source
8029
+ fn dirlight_filterColor(color: vec4<f32>, inputs: DirlightInputs) -> vec4<f32> {
8030
+ // TODO - fix default light direction
8031
+ // let lightDirection = dirlight.lightDirection;
8032
+ let lightDirection = vec3<f32>(1, 1, 1);
8033
+ let d: f32 = abs(dot(inputs.normal, normalize(lightDirection)));
8034
+ return vec4<f32>(color.rgb * d, color.a);
8035
+ }
8036
+ `
8037
+ );
8038
+ var VS_GLSL = (
8039
+ /* glsl */
8040
+ `out vec3 dirlight_vNormal;
8283
8041
 
8284
- return s;
8042
+ void dirlight_setNormal(vec3 normal) {
8043
+ dirlight_vNormal = normalize(normal);
8285
8044
  }
8045
+ `
8046
+ );
8047
+ var FS_GLSL = (
8048
+ /* glsl */
8049
+ `uniform dirlightUniforms {
8050
+ vec3 lightDirection;
8051
+ } dirlight;
8286
8052
 
8287
- vec2 cos_taylor_fp64(vec2 a) {
8288
- vec2 r, s, t, x;
8053
+ in vec3 dirlight_vNormal;
8289
8054
 
8290
- if (a.x == 0.0 && a.y == 0.0) {
8291
- return vec2(1.0, 0.0);
8055
+ // Returns color attenuated by angle from light source
8056
+ vec4 dirlight_filterColor(vec4 color) {
8057
+ float d = abs(dot(dirlight_vNormal, normalize(dirlight.lightDirection)));
8058
+ return vec4(color.rgb * d, color.a);
8059
+ }
8060
+ `
8061
+ );
8062
+ var dirlight = {
8063
+ props: {},
8064
+ uniforms: {},
8065
+ name: "dirlight",
8066
+ dependencies: [],
8067
+ source: SOURCE_WGSL,
8068
+ vs: VS_GLSL,
8069
+ fs: FS_GLSL,
8070
+ // fragmentInputs: [
8071
+ // {
8072
+ // name: 'dirlight_vNormal',
8073
+ // type: 'vec3<f32>'
8074
+ // }
8075
+ // ],
8076
+ uniformTypes: {
8077
+ lightDirection: "vec3<f32>"
8078
+ },
8079
+ defaultUniforms: {
8080
+ lightDirection: [1, 1, 2]
8081
+ },
8082
+ getUniforms: getUniforms3
8083
+ };
8084
+ function getUniforms3(opts = dirlight.defaultUniforms) {
8085
+ const uniforms = {};
8086
+ if (opts.lightDirection) {
8087
+ uniforms.dirlight_uLightDirection = opts.lightDirection;
8088
+ }
8089
+ return uniforms;
8292
8090
  }
8293
8091
 
8294
- x = -mul_fp64(a, a);
8295
- r = x;
8296
- s = sum_fp64(vec2(1.0, 0.0), r * 0.5);
8297
-
8298
- r = mul_fp64(r, x);
8299
- t = mul_fp64(r, INVERSE_FACTORIAL_4_FP64);
8300
- s = sum_fp64(s, t);
8301
-
8302
- r = mul_fp64(r, x);
8303
- t = mul_fp64(r, INVERSE_FACTORIAL_6_FP64);
8304
- s = sum_fp64(s, t);
8092
+ // src/modules/lighting/phong-material/phong-shaders-glsl.ts
8093
+ var PHONG_VS = (
8094
+ /* glsl */
8095
+ `uniform phongMaterialUniforms {
8096
+ uniform float ambient;
8097
+ uniform float diffuse;
8098
+ uniform float shininess;
8099
+ uniform vec3 specularColor;
8100
+ } material;
8101
+ `
8102
+ );
8103
+ var PHONG_FS = (
8104
+ /* glsl */
8105
+ `uniform phongMaterialUniforms {
8106
+ uniform float ambient;
8107
+ uniform float diffuse;
8108
+ uniform float shininess;
8109
+ uniform vec3 specularColor;
8110
+ } material;
8305
8111
 
8306
- /* keep the following commented code in case we need them
8307
- for extra accuracy from the Taylor expansion*/
8112
+ vec3 lighting_getLightColor(vec3 surfaceColor, vec3 light_direction, vec3 view_direction, vec3 normal_worldspace, vec3 color) {
8113
+ vec3 halfway_direction = normalize(light_direction + view_direction);
8114
+ float lambertian = dot(light_direction, normal_worldspace);
8115
+ float specular = 0.0;
8116
+ if (lambertian > 0.0) {
8117
+ float specular_angle = max(dot(normal_worldspace, halfway_direction), 0.0);
8118
+ specular = pow(specular_angle, material.shininess);
8119
+ }
8120
+ lambertian = max(lambertian, 0.0);
8121
+ return (lambertian * material.diffuse * surfaceColor + specular * material.specularColor) * color;
8122
+ }
8308
8123
 
8309
- // r = mul_fp64(r, x);
8310
- // t = mul_fp64(r, INVERSE_FACTORIAL_8_FP64);
8311
- // s = sum_fp64(s, t);
8124
+ vec3 lighting_getLightColor(vec3 surfaceColor, vec3 cameraPosition, vec3 position_worldspace, vec3 normal_worldspace) {
8125
+ vec3 lightColor = surfaceColor;
8312
8126
 
8313
- // r = mul_fp64(r, x);
8314
- // t = mul_fp64(r, INVERSE_FACTORIAL_10_FP64);
8315
- // s = sum_fp64(s, t);
8127
+ if (lighting.enabled == 0) {
8128
+ return lightColor;
8129
+ }
8316
8130
 
8317
- return s;
8318
- }
8131
+ vec3 view_direction = normalize(cameraPosition - position_worldspace);
8132
+ lightColor = material.ambient * surfaceColor * lighting.ambientColor;
8319
8133
 
8320
- void sincos_taylor_fp64(vec2 a, out vec2 sin_t, out vec2 cos_t) {
8321
- if (a.x == 0.0 && a.y == 0.0) {
8322
- sin_t = vec2(0.0, 0.0);
8323
- cos_t = vec2(1.0, 0.0);
8134
+ for (int i = 0; i < lighting.pointLightCount; i++) {
8135
+ PointLight pointLight = lighting_getPointLight(i);
8136
+ vec3 light_position_worldspace = pointLight.position;
8137
+ vec3 light_direction = normalize(light_position_worldspace - position_worldspace);
8138
+ float light_attenuation = getPointLightAttenuation(pointLight, distance(light_position_worldspace, position_worldspace));
8139
+ lightColor += lighting_getLightColor(surfaceColor, light_direction, view_direction, normal_worldspace, pointLight.color / light_attenuation);
8324
8140
  }
8325
8141
 
8326
- sin_t = sin_taylor_fp64(a);
8327
- cos_t = sqrt_fp64(sub_fp64(vec2(1.0, 0.0), mul_fp64(sin_t, sin_t)));
8142
+ int totalLights = min(MAX_LIGHTS, lighting.pointLightCount + lighting.directionalLightCount);
8143
+ for (int i = lighting.pointLightCount; i < totalLights; i++) {
8144
+ DirectionalLight directionalLight = lighting_getDirectionalLight(i);
8145
+ lightColor += lighting_getLightColor(surfaceColor, -directionalLight.direction, view_direction, normal_worldspace, directionalLight.color);
8146
+ }
8147
+
8148
+ return lightColor;
8328
8149
  }
8150
+ `
8151
+ );
8329
8152
 
8330
- vec2 sin_fp64(vec2 a) {
8331
- if (a.x == 0.0 && a.y == 0.0) {
8332
- return vec2(0.0, 0.0);
8153
+ // src/modules/lighting/gouraud-material/gouraud-material.ts
8154
+ var gouraudMaterial = {
8155
+ props: {},
8156
+ name: "gouraudMaterial",
8157
+ // Note these are switched between phong and gouraud
8158
+ vs: PHONG_FS.replace("phongMaterial", "gouraudMaterial"),
8159
+ fs: PHONG_VS.replace("phongMaterial", "gouraudMaterial"),
8160
+ defines: {
8161
+ LIGHTING_VERTEX: 1
8162
+ },
8163
+ dependencies: [lighting],
8164
+ uniformTypes: {
8165
+ ambient: "f32",
8166
+ diffuse: "f32",
8167
+ shininess: "f32",
8168
+ specularColor: "vec3<f32>"
8169
+ },
8170
+ defaultUniforms: {
8171
+ ambient: 0.35,
8172
+ diffuse: 0.6,
8173
+ shininess: 32,
8174
+ specularColor: [0.15, 0.15, 0.15]
8175
+ },
8176
+ getUniforms(props) {
8177
+ const uniforms = { ...props };
8178
+ if (uniforms.specularColor) {
8179
+ uniforms.specularColor = uniforms.specularColor.map((x) => x / 255);
8180
+ }
8181
+ return { ...gouraudMaterial.defaultUniforms, ...uniforms };
8333
8182
  }
8183
+ };
8334
8184
 
8335
- // 2pi range reduction
8336
- vec2 z = nint_fp64(div_fp64(a, TWO_PI_FP64));
8337
- vec2 r = sub_fp64(a, mul_fp64(TWO_PI_FP64, z));
8185
+ // src/modules/lighting/phong-material/phong-shaders-wgsl.ts
8186
+ var PHONG_WGSL = (
8187
+ /* wgsl */
8188
+ `struct phongMaterialUniforms {
8189
+ ambient: f32,
8190
+ diffuse: f32,
8191
+ shininess: f32,
8192
+ specularColor: vec3<f32>,
8193
+ };
8338
8194
 
8339
- vec2 t;
8340
- float q = floor(r.x / PI_2_FP64.x + 0.5);
8341
- int j = int(q);
8195
+ @binding(2) @group(0) var<uniform> material : phongMaterialUniforms;
8342
8196
 
8343
- if (j < -2 || j > 2) {
8344
- return vec2(0.0 / 0.0, 0.0 / 0.0);
8345
- }
8197
+ fn lighting_getLightColor(surfaceColor: vec3<f32>, light_direction: vec3<f32>, view_direction: vec3<f32>, normal_worldspace: vec3<f32>, color: vec3<f32>) -> vec3<f32> {
8198
+ let halfway_direction: vec3<f32> = normalize(light_direction + view_direction);
8199
+ var lambertian: f32 = dot(light_direction, normal_worldspace);
8200
+ var specular: f32 = 0.0;
8201
+ if (lambertian > 0.0) {
8202
+ let specular_angle = max(dot(normal_worldspace, halfway_direction), 0.0);
8203
+ specular = pow(specular_angle, material.shininess);
8204
+ }
8205
+ lambertian = max(lambertian, 0.0);
8206
+ return (lambertian * material.diffuse * surfaceColor + specular * material.specularColor) * color;
8207
+ }
8346
8208
 
8347
- t = sub_fp64(r, mul_fp64(PI_2_FP64, vec2(q, 0.0)));
8209
+ fn lighting_getLightColor2(surfaceColor: vec3<f32>, cameraPosition: vec3<f32>, position_worldspace: vec3<f32>, normal_worldspace: vec3<f32>) -> vec3<f32> {
8210
+ var lightColor: vec3<f32> = surfaceColor;
8348
8211
 
8349
- q = floor(t.x / PI_16_FP64.x + 0.5);
8350
- int k = int(q);
8212
+ if (lighting.enabled == 0) {
8213
+ return lightColor;
8214
+ }
8351
8215
 
8352
- if (k == 0) {
8353
- if (j == 0) {
8354
- return sin_taylor_fp64(t);
8355
- } else if (j == 1) {
8356
- return cos_taylor_fp64(t);
8357
- } else if (j == -1) {
8358
- return -cos_taylor_fp64(t);
8359
- } else {
8360
- return -sin_taylor_fp64(t);
8361
- }
8362
- }
8216
+ let view_direction: vec3<f32> = normalize(cameraPosition - position_worldspace);
8217
+ lightColor = material.ambient * surfaceColor * lighting.ambientColor;
8363
8218
 
8364
- int abs_k = int(abs(float(k)));
8219
+ if (lighting.lightType == 0) {
8220
+ let pointLight: PointLight = lighting_getPointLight(0);
8221
+ let light_position_worldspace: vec3<f32> = pointLight.position;
8222
+ let light_direction: vec3<f32> = normalize(light_position_worldspace - position_worldspace);
8223
+ lightColor += lighting_getLightColor(surfaceColor, light_direction, view_direction, normal_worldspace, pointLight.color);
8224
+ } else if (lighting.lightType == 1) {
8225
+ var directionalLight: DirectionalLight = lighting_getDirectionalLight(0);
8226
+ lightColor += lighting_getLightColor(surfaceColor, -directionalLight.direction, view_direction, normal_worldspace, directionalLight.color);
8227
+ }
8228
+
8229
+ return lightColor;
8230
+ /*
8231
+ for (int i = 0; i < MAX_LIGHTS; i++) {
8232
+ if (i >= lighting.pointLightCount) {
8233
+ break;
8234
+ }
8235
+ PointLight pointLight = lighting.pointLight[i];
8236
+ vec3 light_position_worldspace = pointLight.position;
8237
+ vec3 light_direction = normalize(light_position_worldspace - position_worldspace);
8238
+ lightColor += lighting_getLightColor(surfaceColor, light_direction, view_direction, normal_worldspace, pointLight.color);
8239
+ }
8365
8240
 
8366
- if (abs_k > 4) {
8367
- return vec2(0.0 / 0.0, 0.0 / 0.0);
8368
- } else {
8369
- t = sub_fp64(t, mul_fp64(PI_16_FP64, vec2(q, 0.0)));
8241
+ for (int i = 0; i < MAX_LIGHTS; i++) {
8242
+ if (i >= lighting.directionalLightCount) {
8243
+ break;
8370
8244
  }
8245
+ DirectionalLight directionalLight = lighting.directionalLight[i];
8246
+ lightColor += lighting_getLightColor(surfaceColor, -directionalLight.direction, view_direction, normal_worldspace, directionalLight.color);
8247
+ }
8248
+ */
8249
+ }
8371
8250
 
8372
- vec2 u = vec2(0.0, 0.0);
8373
- vec2 v = vec2(0.0, 0.0);
8251
+ fn lighting_getSpecularLightColor(cameraPosition: vec3<f32>, position_worldspace: vec3<f32>, normal_worldspace: vec3<f32>) -> vec3<f32>{
8252
+ var lightColor = vec3<f32>(0, 0, 0);
8253
+ let surfaceColor = vec3<f32>(0, 0, 0);
8374
8254
 
8375
- #if defined(NVIDIA_FP64_WORKAROUND) || defined(INTEL_FP64_WORKAROUND)
8376
- if (abs(float(abs_k) - 1.0) < 0.5) {
8377
- u = COS_TABLE_0_FP64;
8378
- v = SIN_TABLE_0_FP64;
8379
- } else if (abs(float(abs_k) - 2.0) < 0.5) {
8380
- u = COS_TABLE_1_FP64;
8381
- v = SIN_TABLE_1_FP64;
8382
- } else if (abs(float(abs_k) - 3.0) < 0.5) {
8383
- u = COS_TABLE_2_FP64;
8384
- v = SIN_TABLE_2_FP64;
8385
- } else if (abs(float(abs_k) - 4.0) < 0.5) {
8386
- u = COS_TABLE_3_FP64;
8387
- v = SIN_TABLE_3_FP64;
8255
+ if (lighting.enabled == 0) {
8256
+ let view_direction = normalize(cameraPosition - position_worldspace);
8257
+
8258
+ switch (lighting.lightType) {
8259
+ case 0, default: {
8260
+ let pointLight: PointLight = lighting_getPointLight(0);
8261
+ let light_position_worldspace: vec3<f32> = pointLight.position;
8262
+ let light_direction: vec3<f32> = normalize(light_position_worldspace - position_worldspace);
8263
+ lightColor += lighting_getLightColor(surfaceColor, light_direction, view_direction, normal_worldspace, pointLight.color);
8264
+ }
8265
+ case 1: {
8266
+ let directionalLight: DirectionalLight = lighting_getDirectionalLight(0);
8267
+ lightColor += lighting_getLightColor(surfaceColor, -directionalLight.direction, view_direction, normal_worldspace, directionalLight.color);
8268
+ }
8388
8269
  }
8389
- #else
8390
- if (abs_k == 1) {
8391
- u = COS_TABLE_0_FP64;
8392
- v = SIN_TABLE_0_FP64;
8393
- } else if (abs_k == 2) {
8394
- u = COS_TABLE_1_FP64;
8395
- v = SIN_TABLE_1_FP64;
8396
- } else if (abs_k == 3) {
8397
- u = COS_TABLE_2_FP64;
8398
- v = SIN_TABLE_2_FP64;
8399
- } else if (abs_k == 4) {
8400
- u = COS_TABLE_3_FP64;
8401
- v = SIN_TABLE_3_FP64;
8270
+ }
8271
+ return lightColor;
8272
+ }
8273
+ `
8274
+ );
8275
+
8276
+ // src/modules/lighting/phong-material/phong-material.ts
8277
+ var phongMaterial = {
8278
+ name: "phongMaterial",
8279
+ dependencies: [lighting],
8280
+ // Note these are switched between phong and gouraud
8281
+ source: PHONG_WGSL,
8282
+ vs: PHONG_VS,
8283
+ fs: PHONG_FS,
8284
+ defines: {
8285
+ LIGHTING_FRAGMENT: 1
8286
+ },
8287
+ uniformTypes: {
8288
+ ambient: "f32",
8289
+ diffuse: "f32",
8290
+ shininess: "f32",
8291
+ specularColor: "vec3<f32>"
8292
+ },
8293
+ defaultUniforms: {
8294
+ ambient: 0.35,
8295
+ diffuse: 0.6,
8296
+ shininess: 32,
8297
+ specularColor: [0.15, 0.15, 0.15]
8298
+ },
8299
+ getUniforms(props) {
8300
+ const uniforms = { ...props };
8301
+ if (uniforms.specularColor) {
8302
+ uniforms.specularColor = uniforms.specularColor.map((x) => x / 255);
8303
+ }
8304
+ return { ...phongMaterial.defaultUniforms, ...uniforms };
8402
8305
  }
8403
- #endif
8306
+ };
8404
8307
 
8405
- vec2 sin_t, cos_t;
8406
- sincos_taylor_fp64(t, sin_t, cos_t);
8308
+ // src/modules/lighting/pbr-material/pbr-vertex-glsl.ts
8309
+ var vs2 = (
8310
+ /* glsl */
8311
+ `out vec3 pbr_vPosition;
8312
+ out vec2 pbr_vUV;
8407
8313
 
8314
+ #ifdef HAS_NORMALS
8315
+ # ifdef HAS_TANGENTS
8316
+ out mat3 pbr_vTBN;
8317
+ # else
8318
+ out vec3 pbr_vNormal;
8319
+ # endif
8320
+ #endif
8408
8321
 
8322
+ void pbr_setPositionNormalTangentUV(vec4 position, vec4 normal, vec4 tangent, vec2 uv)
8323
+ {
8324
+ vec4 pos = pbrProjection.modelMatrix * position;
8325
+ pbr_vPosition = vec3(pos.xyz) / pos.w;
8409
8326
 
8410
- vec2 result = vec2(0.0, 0.0);
8411
- if (j == 0) {
8412
- if (k > 0) {
8413
- result = sum_fp64(mul_fp64(u, sin_t), mul_fp64(v, cos_t));
8414
- } else {
8415
- result = sub_fp64(mul_fp64(u, sin_t), mul_fp64(v, cos_t));
8416
- }
8417
- } else if (j == 1) {
8418
- if (k > 0) {
8419
- result = sub_fp64(mul_fp64(u, cos_t), mul_fp64(v, sin_t));
8420
- } else {
8421
- result = sum_fp64(mul_fp64(u, cos_t), mul_fp64(v, sin_t));
8422
- }
8423
- } else if (j == -1) {
8424
- if (k > 0) {
8425
- result = sub_fp64(mul_fp64(v, sin_t), mul_fp64(u, cos_t));
8426
- } else {
8427
- result = -sum_fp64(mul_fp64(v, sin_t), mul_fp64(u, cos_t));
8428
- }
8429
- } else {
8430
- if (k > 0) {
8431
- result = -sum_fp64(mul_fp64(u, sin_t), mul_fp64(v, cos_t));
8432
- } else {
8433
- result = sub_fp64(mul_fp64(v, cos_t), mul_fp64(u, sin_t));
8434
- }
8435
- }
8327
+ #ifdef HAS_NORMALS
8328
+ #ifdef HAS_TANGENTS
8329
+ vec3 normalW = normalize(vec3(pbrProjection.normalMatrix * vec4(normal.xyz, 0.0)));
8330
+ vec3 tangentW = normalize(vec3(pbrProjection.modelMatrix * vec4(tangent.xyz, 0.0)));
8331
+ vec3 bitangentW = cross(normalW, tangentW) * tangent.w;
8332
+ pbr_vTBN = mat3(tangentW, bitangentW, normalW);
8333
+ #else // HAS_TANGENTS != 1
8334
+ pbr_vNormal = normalize(vec3(pbrProjection.modelMatrix * vec4(normal.xyz, 0.0)));
8335
+ #endif
8336
+ #endif
8436
8337
 
8437
- return result;
8338
+ #ifdef HAS_UV
8339
+ pbr_vUV = uv;
8340
+ #else
8341
+ pbr_vUV = vec2(0.,0.);
8342
+ #endif
8438
8343
  }
8344
+ `
8345
+ );
8439
8346
 
8440
- vec2 cos_fp64(vec2 a) {
8441
- if (a.x == 0.0 && a.y == 0.0) {
8442
- return vec2(1.0, 0.0);
8443
- }
8347
+ // src/modules/lighting/pbr-material/pbr-fragment-glsl.ts
8348
+ var fs3 = (
8349
+ /* glsl */
8350
+ `precision highp float;
8444
8351
 
8445
- // 2pi range reduction
8446
- vec2 z = nint_fp64(div_fp64(a, TWO_PI_FP64));
8447
- vec2 r = sub_fp64(a, mul_fp64(TWO_PI_FP64, z));
8352
+ uniform pbrMaterialUniforms {
8353
+ // Material is unlit
8354
+ bool unlit;
8448
8355
 
8449
- vec2 t;
8450
- float q = floor(r.x / PI_2_FP64.x + 0.5);
8451
- int j = int(q);
8356
+ // Base color map
8357
+ bool baseColorMapEnabled;
8358
+ vec4 baseColorFactor;
8452
8359
 
8453
- if (j < -2 || j > 2) {
8454
- return vec2(0.0 / 0.0, 0.0 / 0.0);
8455
- }
8360
+ bool normalMapEnabled;
8361
+ float normalScale; // #ifdef HAS_NORMALMAP
8456
8362
 
8457
- t = sub_fp64(r, mul_fp64(PI_2_FP64, vec2(q, 0.0)));
8363
+ bool emissiveMapEnabled;
8364
+ vec3 emissiveFactor; // #ifdef HAS_EMISSIVEMAP
8458
8365
 
8459
- q = floor(t.x / PI_16_FP64.x + 0.5);
8460
- int k = int(q);
8366
+ vec2 metallicRoughnessValues;
8367
+ bool metallicRoughnessMapEnabled;
8461
8368
 
8462
- if (k == 0) {
8463
- if (j == 0) {
8464
- return cos_taylor_fp64(t);
8465
- } else if (j == 1) {
8466
- return -sin_taylor_fp64(t);
8467
- } else if (j == -1) {
8468
- return sin_taylor_fp64(t);
8469
- } else {
8470
- return -cos_taylor_fp64(t);
8471
- }
8472
- }
8369
+ bool occlusionMapEnabled;
8370
+ float occlusionStrength; // #ifdef HAS_OCCLUSIONMAP
8371
+
8372
+ bool alphaCutoffEnabled;
8373
+ float alphaCutoff; // #ifdef ALPHA_CUTOFF
8374
+
8375
+ // IBL
8376
+ bool IBLenabled;
8377
+ vec2 scaleIBLAmbient; // #ifdef USE_IBL
8378
+
8379
+ // debugging flags used for shader output of intermediate PBR variables
8380
+ // #ifdef PBR_DEBUG
8381
+ vec4 scaleDiffBaseMR;
8382
+ vec4 scaleFGDSpec;
8383
+ // #endif
8384
+ } pbrMaterial;
8473
8385
 
8474
- int abs_k = int(abs(float(k)));
8386
+ // Samplers
8387
+ #ifdef HAS_BASECOLORMAP
8388
+ uniform sampler2D pbr_baseColorSampler;
8389
+ #endif
8390
+ #ifdef HAS_NORMALMAP
8391
+ uniform sampler2D pbr_normalSampler;
8392
+ #endif
8393
+ #ifdef HAS_EMISSIVEMAP
8394
+ uniform sampler2D pbr_emissiveSampler;
8395
+ #endif
8396
+ #ifdef HAS_METALROUGHNESSMAP
8397
+ uniform sampler2D pbr_metallicRoughnessSampler;
8398
+ #endif
8399
+ #ifdef HAS_OCCLUSIONMAP
8400
+ uniform sampler2D pbr_occlusionSampler;
8401
+ #endif
8402
+ #ifdef USE_IBL
8403
+ uniform samplerCube pbr_diffuseEnvSampler;
8404
+ uniform samplerCube pbr_specularEnvSampler;
8405
+ uniform sampler2D pbr_brdfLUT;
8406
+ #endif
8475
8407
 
8476
- if (abs_k > 4) {
8477
- return vec2(0.0 / 0.0, 0.0 / 0.0);
8478
- } else {
8479
- t = sub_fp64(t, mul_fp64(PI_16_FP64, vec2(q, 0.0)));
8480
- }
8408
+ // Inputs from vertex shader
8481
8409
 
8482
- vec2 u = vec2(0.0, 0.0);
8483
- vec2 v = vec2(0.0, 0.0);
8410
+ in vec3 pbr_vPosition;
8411
+ in vec2 pbr_vUV;
8484
8412
 
8485
- #if defined(NVIDIA_FP64_WORKAROUND) || defined(INTEL_FP64_WORKAROUND)
8486
- if (abs(float(abs_k) - 1.0) < 0.5) {
8487
- u = COS_TABLE_0_FP64;
8488
- v = SIN_TABLE_0_FP64;
8489
- } else if (abs(float(abs_k) - 2.0) < 0.5) {
8490
- u = COS_TABLE_1_FP64;
8491
- v = SIN_TABLE_1_FP64;
8492
- } else if (abs(float(abs_k) - 3.0) < 0.5) {
8493
- u = COS_TABLE_2_FP64;
8494
- v = SIN_TABLE_2_FP64;
8495
- } else if (abs(float(abs_k) - 4.0) < 0.5) {
8496
- u = COS_TABLE_3_FP64;
8497
- v = SIN_TABLE_3_FP64;
8498
- }
8413
+ #ifdef HAS_NORMALS
8414
+ #ifdef HAS_TANGENTS
8415
+ in mat3 pbr_vTBN;
8499
8416
  #else
8500
- if (abs_k == 1) {
8501
- u = COS_TABLE_0_FP64;
8502
- v = SIN_TABLE_0_FP64;
8503
- } else if (abs_k == 2) {
8504
- u = COS_TABLE_1_FP64;
8505
- v = SIN_TABLE_1_FP64;
8506
- } else if (abs_k == 3) {
8507
- u = COS_TABLE_2_FP64;
8508
- v = SIN_TABLE_2_FP64;
8509
- } else if (abs_k == 4) {
8510
- u = COS_TABLE_3_FP64;
8511
- v = SIN_TABLE_3_FP64;
8512
- }
8417
+ in vec3 pbr_vNormal;
8418
+ #endif
8513
8419
  #endif
8514
8420
 
8515
- vec2 sin_t, cos_t;
8516
- sincos_taylor_fp64(t, sin_t, cos_t);
8421
+ // Encapsulate the various inputs used by the various functions in the shading equation
8422
+ // We store values in this struct to simplify the integration of alternative implementations
8423
+ // of the shading terms, outlined in the Readme.MD Appendix.
8424
+ struct PBRInfo {
8425
+ float NdotL; // cos angle between normal and light direction
8426
+ float NdotV; // cos angle between normal and view direction
8427
+ float NdotH; // cos angle between normal and half vector
8428
+ float LdotH; // cos angle between light direction and half vector
8429
+ float VdotH; // cos angle between view direction and half vector
8430
+ float perceptualRoughness; // roughness value, as authored by the model creator (input to shader)
8431
+ float metalness; // metallic value at the surface
8432
+ vec3 reflectance0; // full reflectance color (normal incidence angle)
8433
+ vec3 reflectance90; // reflectance color at grazing angle
8434
+ float alphaRoughness; // roughness mapped to a more linear change in the roughness (proposed by [2])
8435
+ vec3 diffuseColor; // color contribution from diffuse lighting
8436
+ vec3 specularColor; // color contribution from specular lighting
8437
+ vec3 n; // normal at surface point
8438
+ vec3 v; // vector from surface point to camera
8439
+ };
8517
8440
 
8518
- vec2 result = vec2(0.0, 0.0);
8519
- if (j == 0) {
8520
- if (k > 0) {
8521
- result = sub_fp64(mul_fp64(u, cos_t), mul_fp64(v, sin_t));
8522
- } else {
8523
- result = sum_fp64(mul_fp64(u, cos_t), mul_fp64(v, sin_t));
8524
- }
8525
- } else if (j == 1) {
8526
- if (k > 0) {
8527
- result = -sum_fp64(mul_fp64(u, sin_t), mul_fp64(v, cos_t));
8528
- } else {
8529
- result = sub_fp64(mul_fp64(v, cos_t), mul_fp64(u, sin_t));
8530
- }
8531
- } else if (j == -1) {
8532
- if (k > 0) {
8533
- result = sum_fp64(mul_fp64(u, sin_t), mul_fp64(v, cos_t));
8534
- } else {
8535
- result = sub_fp64(mul_fp64(u, sin_t), mul_fp64(v, cos_t));
8536
- }
8537
- } else {
8538
- if (k > 0) {
8539
- result = sub_fp64(mul_fp64(v, sin_t), mul_fp64(u, cos_t));
8540
- } else {
8541
- result = -sum_fp64(mul_fp64(u, cos_t), mul_fp64(v, sin_t));
8542
- }
8543
- }
8441
+ const float M_PI = 3.141592653589793;
8442
+ const float c_MinRoughness = 0.04;
8544
8443
 
8545
- return result;
8444
+ vec4 SRGBtoLINEAR(vec4 srgbIn)
8445
+ {
8446
+ #ifdef MANUAL_SRGB
8447
+ #ifdef SRGB_FAST_APPROXIMATION
8448
+ vec3 linOut = pow(srgbIn.xyz,vec3(2.2));
8449
+ #else // SRGB_FAST_APPROXIMATION
8450
+ vec3 bLess = step(vec3(0.04045),srgbIn.xyz);
8451
+ vec3 linOut = mix( srgbIn.xyz/vec3(12.92), pow((srgbIn.xyz+vec3(0.055))/vec3(1.055),vec3(2.4)), bLess );
8452
+ #endif //SRGB_FAST_APPROXIMATION
8453
+ return vec4(linOut,srgbIn.w);;
8454
+ #else //MANUAL_SRGB
8455
+ return srgbIn;
8456
+ #endif //MANUAL_SRGB
8546
8457
  }
8547
8458
 
8548
- vec2 tan_fp64(vec2 a) {
8549
- vec2 sin_a;
8550
- vec2 cos_a;
8551
-
8552
- if (a.x == 0.0 && a.y == 0.0) {
8553
- return vec2(0.0, 0.0);
8554
- }
8555
-
8556
- // 2pi range reduction
8557
- vec2 z = nint_fp64(div_fp64(a, TWO_PI_FP64));
8558
- vec2 r = sub_fp64(a, mul_fp64(TWO_PI_FP64, z));
8559
-
8560
- vec2 t;
8561
- float q = floor(r.x / PI_2_FP64.x + 0.5);
8562
- int j = int(q);
8459
+ // Find the normal for this fragment, pulling either from a predefined normal map
8460
+ // or from the interpolated mesh normal and tangent attributes.
8461
+ vec3 getNormal()
8462
+ {
8463
+ // Retrieve the tangent space matrix
8464
+ #ifndef HAS_TANGENTS
8465
+ vec3 pos_dx = dFdx(pbr_vPosition);
8466
+ vec3 pos_dy = dFdy(pbr_vPosition);
8467
+ vec3 tex_dx = dFdx(vec3(pbr_vUV, 0.0));
8468
+ vec3 tex_dy = dFdy(vec3(pbr_vUV, 0.0));
8469
+ vec3 t = (tex_dy.t * pos_dx - tex_dx.t * pos_dy) / (tex_dx.s * tex_dy.t - tex_dy.s * tex_dx.t);
8563
8470
 
8471
+ #ifdef HAS_NORMALS
8472
+ vec3 ng = normalize(pbr_vNormal);
8473
+ #else
8474
+ vec3 ng = cross(pos_dx, pos_dy);
8475
+ #endif
8564
8476
 
8565
- if (j < -2 || j > 2) {
8566
- return vec2(0.0 / 0.0, 0.0 / 0.0);
8567
- }
8477
+ t = normalize(t - ng * dot(ng, t));
8478
+ vec3 b = normalize(cross(ng, t));
8479
+ mat3 tbn = mat3(t, b, ng);
8480
+ #else // HAS_TANGENTS
8481
+ mat3 tbn = pbr_vTBN;
8482
+ #endif
8568
8483
 
8569
- t = sub_fp64(r, mul_fp64(PI_2_FP64, vec2(q, 0.0)));
8484
+ #ifdef HAS_NORMALMAP
8485
+ vec3 n = texture(pbr_normalSampler, pbr_vUV).rgb;
8486
+ n = normalize(tbn * ((2.0 * n - 1.0) * vec3(pbrMaterial.normalScale, pbrMaterial.normalScale, 1.0)));
8487
+ #else
8488
+ // The tbn matrix is linearly interpolated, so we need to re-normalize
8489
+ vec3 n = normalize(tbn[2].xyz);
8490
+ #endif
8570
8491
 
8571
- q = floor(t.x / PI_16_FP64.x + 0.5);
8572
- int k = int(q);
8573
- int abs_k = int(abs(float(k)));
8492
+ return n;
8493
+ }
8574
8494
 
8575
- // We just can't get PI/16 * 3.0 very accurately.
8576
- // so let's just store it
8577
- if (abs_k > 4) {
8578
- return vec2(0.0 / 0.0, 0.0 / 0.0);
8579
- } else {
8580
- t = sub_fp64(t, mul_fp64(PI_16_FP64, vec2(q, 0.0)));
8581
- }
8495
+ // Calculation of the lighting contribution from an optional Image Based Light source.
8496
+ // Precomputed Environment Maps are required uniform inputs and are computed as outlined in [1].
8497
+ // See our README.md on Environment Maps [3] for additional discussion.
8498
+ #ifdef USE_IBL
8499
+ vec3 getIBLContribution(PBRInfo pbrInfo, vec3 n, vec3 reflection)
8500
+ {
8501
+ float mipCount = 9.0; // resolution of 512x512
8502
+ float lod = (pbrInfo.perceptualRoughness * mipCount);
8503
+ // retrieve a scale and bias to F0. See [1], Figure 3
8504
+ vec3 brdf = SRGBtoLINEAR(texture(pbr_brdfLUT,
8505
+ vec2(pbrInfo.NdotV, 1.0 - pbrInfo.perceptualRoughness))).rgb;
8506
+ vec3 diffuseLight = SRGBtoLINEAR(texture(pbr_diffuseEnvSampler, n)).rgb;
8582
8507
 
8508
+ #ifdef USE_TEX_LOD
8509
+ vec3 specularLight = SRGBtoLINEAR(texture(pbr_specularEnvSampler, reflection, lod)).rgb;
8510
+ #else
8511
+ vec3 specularLight = SRGBtoLINEAR(texture(pbr_specularEnvSampler, reflection)).rgb;
8512
+ #endif
8583
8513
 
8584
- vec2 u = vec2(0.0, 0.0);
8585
- vec2 v = vec2(0.0, 0.0);
8514
+ vec3 diffuse = diffuseLight * pbrInfo.diffuseColor;
8515
+ vec3 specular = specularLight * (pbrInfo.specularColor * brdf.x + brdf.y);
8586
8516
 
8587
- vec2 sin_t, cos_t;
8588
- vec2 s, c;
8589
- sincos_taylor_fp64(t, sin_t, cos_t);
8517
+ // For presentation, this allows us to disable IBL terms
8518
+ diffuse *= pbrMaterial.scaleIBLAmbient.x;
8519
+ specular *= pbrMaterial.scaleIBLAmbient.y;
8590
8520
 
8591
- if (k == 0) {
8592
- s = sin_t;
8593
- c = cos_t;
8594
- } else {
8595
- #if defined(NVIDIA_FP64_WORKAROUND) || defined(INTEL_FP64_WORKAROUND)
8596
- if (abs(float(abs_k) - 1.0) < 0.5) {
8597
- u = COS_TABLE_0_FP64;
8598
- v = SIN_TABLE_0_FP64;
8599
- } else if (abs(float(abs_k) - 2.0) < 0.5) {
8600
- u = COS_TABLE_1_FP64;
8601
- v = SIN_TABLE_1_FP64;
8602
- } else if (abs(float(abs_k) - 3.0) < 0.5) {
8603
- u = COS_TABLE_2_FP64;
8604
- v = SIN_TABLE_2_FP64;
8605
- } else if (abs(float(abs_k) - 4.0) < 0.5) {
8606
- u = COS_TABLE_3_FP64;
8607
- v = SIN_TABLE_3_FP64;
8608
- }
8609
- #else
8610
- if (abs_k == 1) {
8611
- u = COS_TABLE_0_FP64;
8612
- v = SIN_TABLE_0_FP64;
8613
- } else if (abs_k == 2) {
8614
- u = COS_TABLE_1_FP64;
8615
- v = SIN_TABLE_1_FP64;
8616
- } else if (abs_k == 3) {
8617
- u = COS_TABLE_2_FP64;
8618
- v = SIN_TABLE_2_FP64;
8619
- } else if (abs_k == 4) {
8620
- u = COS_TABLE_3_FP64;
8621
- v = SIN_TABLE_3_FP64;
8622
- }
8521
+ return diffuse + specular;
8522
+ }
8623
8523
  #endif
8624
- if (k > 0) {
8625
- s = sum_fp64(mul_fp64(u, sin_t), mul_fp64(v, cos_t));
8626
- c = sub_fp64(mul_fp64(u, cos_t), mul_fp64(v, sin_t));
8627
- } else {
8628
- s = sub_fp64(mul_fp64(u, sin_t), mul_fp64(v, cos_t));
8629
- c = sum_fp64(mul_fp64(u, cos_t), mul_fp64(v, sin_t));
8630
- }
8631
- }
8632
8524
 
8633
- if (j == 0) {
8634
- sin_a = s;
8635
- cos_a = c;
8636
- } else if (j == 1) {
8637
- sin_a = c;
8638
- cos_a = -s;
8639
- } else if (j == -1) {
8640
- sin_a = -c;
8641
- cos_a = s;
8642
- } else {
8643
- sin_a = -s;
8644
- cos_a = -c;
8645
- }
8646
- return div_fp64(sin_a, cos_a);
8525
+ // Basic Lambertian diffuse
8526
+ // Implementation from Lambert's Photometria https://archive.org/details/lambertsphotome00lambgoog
8527
+ // See also [1], Equation 1
8528
+ vec3 diffuse(PBRInfo pbrInfo)
8529
+ {
8530
+ return pbrInfo.diffuseColor / M_PI;
8647
8531
  }
8648
8532
 
8649
- vec2 radians_fp64(vec2 degree) {
8650
- return mul_fp64(degree, PI_180_FP64);
8533
+ // The following equation models the Fresnel reflectance term of the spec equation (aka F())
8534
+ // Implementation of fresnel from [4], Equation 15
8535
+ vec3 specularReflection(PBRInfo pbrInfo)
8536
+ {
8537
+ return pbrInfo.reflectance0 +
8538
+ (pbrInfo.reflectance90 - pbrInfo.reflectance0) *
8539
+ pow(clamp(1.0 - pbrInfo.VdotH, 0.0, 1.0), 5.0);
8651
8540
  }
8652
8541
 
8653
- vec2 mix_fp64(vec2 a, vec2 b, float x) {
8654
- vec2 range = sub_fp64(b, a);
8655
- return sum_fp64(a, mul_fp64(range, vec2(x, 0.0)));
8656
- }
8542
+ // This calculates the specular geometric attenuation (aka G()),
8543
+ // where rougher material will reflect less light back to the viewer.
8544
+ // This implementation is based on [1] Equation 4, and we adopt their modifications to
8545
+ // alphaRoughness as input as originally proposed in [2].
8546
+ float geometricOcclusion(PBRInfo pbrInfo)
8547
+ {
8548
+ float NdotL = pbrInfo.NdotL;
8549
+ float NdotV = pbrInfo.NdotV;
8550
+ float r = pbrInfo.alphaRoughness;
8657
8551
 
8658
- // Vector functions
8659
- // vec2 functions
8660
- void vec2_sum_fp64(vec2 a[2], vec2 b[2], out vec2 out_val[2]) {
8661
- out_val[0] = sum_fp64(a[0], b[0]);
8662
- out_val[1] = sum_fp64(a[1], b[1]);
8552
+ float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL)));
8553
+ float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV)));
8554
+ return attenuationL * attenuationV;
8663
8555
  }
8664
8556
 
8665
- void vec2_sub_fp64(vec2 a[2], vec2 b[2], out vec2 out_val[2]) {
8666
- out_val[0] = sub_fp64(a[0], b[0]);
8667
- out_val[1] = sub_fp64(a[1], b[1]);
8557
+ // The following equation(s) model the distribution of microfacet normals across
8558
+ // the area being drawn (aka D())
8559
+ // Implementation from "Average Irregularity Representation of a Roughened Surface
8560
+ // for Ray Reflection" by T. S. Trowbridge, and K. P. Reitz
8561
+ // Follows the distribution function recommended in the SIGGRAPH 2013 course notes
8562
+ // from EPIC Games [1], Equation 3.
8563
+ float microfacetDistribution(PBRInfo pbrInfo)
8564
+ {
8565
+ float roughnessSq = pbrInfo.alphaRoughness * pbrInfo.alphaRoughness;
8566
+ float f = (pbrInfo.NdotH * roughnessSq - pbrInfo.NdotH) * pbrInfo.NdotH + 1.0;
8567
+ return roughnessSq / (M_PI * f * f);
8668
8568
  }
8669
8569
 
8670
- void vec2_mul_fp64(vec2 a[2], vec2 b[2], out vec2 out_val[2]) {
8671
- out_val[0] = mul_fp64(a[0], b[0]);
8672
- out_val[1] = mul_fp64(a[1], b[1]);
8570
+ void PBRInfo_setAmbientLight(inout PBRInfo pbrInfo) {
8571
+ pbrInfo.NdotL = 1.0;
8572
+ pbrInfo.NdotH = 0.0;
8573
+ pbrInfo.LdotH = 0.0;
8574
+ pbrInfo.VdotH = 1.0;
8673
8575
  }
8674
8576
 
8675
- void vec2_div_fp64(vec2 a[2], vec2 b[2], out vec2 out_val[2]) {
8676
- out_val[0] = div_fp64(a[0], b[0]);
8677
- out_val[1] = div_fp64(a[1], b[1]);
8678
- }
8577
+ void PBRInfo_setDirectionalLight(inout PBRInfo pbrInfo, vec3 lightDirection) {
8578
+ vec3 n = pbrInfo.n;
8579
+ vec3 v = pbrInfo.v;
8580
+ vec3 l = normalize(lightDirection); // Vector from surface point to light
8581
+ vec3 h = normalize(l+v); // Half vector between both l and v
8679
8582
 
8680
- void vec2_mix_fp64(vec2 x[2], vec2 y[2], float a, out vec2 out_val[2]) {
8681
- vec2 range[2];
8682
- vec2_sub_fp64(y, x, range);
8683
- vec2 portion[2];
8684
- portion[0] = range[0] * a;
8685
- portion[1] = range[1] * a;
8686
- vec2_sum_fp64(x, portion, out_val);
8583
+ pbrInfo.NdotL = clamp(dot(n, l), 0.001, 1.0);
8584
+ pbrInfo.NdotH = clamp(dot(n, h), 0.0, 1.0);
8585
+ pbrInfo.LdotH = clamp(dot(l, h), 0.0, 1.0);
8586
+ pbrInfo.VdotH = clamp(dot(v, h), 0.0, 1.0);
8687
8587
  }
8688
8588
 
8689
- vec2 vec2_length_fp64(vec2 x[2]) {
8690
- return sqrt_fp64(sum_fp64(mul_fp64(x[0], x[0]), mul_fp64(x[1], x[1])));
8589
+ void PBRInfo_setPointLight(inout PBRInfo pbrInfo, PointLight pointLight) {
8590
+ vec3 light_direction = normalize(pointLight.position - pbr_vPosition);
8591
+ PBRInfo_setDirectionalLight(pbrInfo, light_direction);
8691
8592
  }
8692
8593
 
8693
- void vec2_normalize_fp64(vec2 x[2], out vec2 out_val[2]) {
8694
- vec2 length = vec2_length_fp64(x);
8695
- vec2 length_vec2[2];
8696
- length_vec2[0] = length;
8697
- length_vec2[1] = length;
8594
+ vec3 calculateFinalColor(PBRInfo pbrInfo, vec3 lightColor) {
8595
+ // Calculate the shading terms for the microfacet specular shading model
8596
+ vec3 F = specularReflection(pbrInfo);
8597
+ float G = geometricOcclusion(pbrInfo);
8598
+ float D = microfacetDistribution(pbrInfo);
8698
8599
 
8699
- vec2_div_fp64(x, length_vec2, out_val);
8600
+ // Calculation of analytical lighting contribution
8601
+ vec3 diffuseContrib = (1.0 - F) * diffuse(pbrInfo);
8602
+ vec3 specContrib = F * G * D / (4.0 * pbrInfo.NdotL * pbrInfo.NdotV);
8603
+ // Obtain final intensity as reflectance (BRDF) scaled by the energy of the light (cosine law)
8604
+ return pbrInfo.NdotL * lightColor * (diffuseContrib + specContrib);
8700
8605
  }
8701
8606
 
8702
- vec2 vec2_distance_fp64(vec2 x[2], vec2 y[2]) {
8703
- vec2 diff[2];
8704
- vec2_sub_fp64(x, y, diff);
8705
- return vec2_length_fp64(diff);
8706
- }
8607
+ vec4 pbr_filterColor(vec4 colorUnused)
8608
+ {
8609
+ // The albedo may be defined from a base texture or a flat color
8610
+ #ifdef HAS_BASECOLORMAP
8611
+ vec4 baseColor = SRGBtoLINEAR(texture(pbr_baseColorSampler, pbr_vUV)) * pbrMaterial.baseColorFactor;
8612
+ #else
8613
+ vec4 baseColor = pbrMaterial.baseColorFactor;
8614
+ #endif
8707
8615
 
8708
- vec2 vec2_dot_fp64(vec2 a[2], vec2 b[2]) {
8709
- vec2 v[2];
8616
+ #ifdef ALPHA_CUTOFF
8617
+ if (baseColor.a < pbrMaterial.alphaCutoff) {
8618
+ discard;
8619
+ }
8620
+ #endif
8621
+
8622
+ vec3 color = vec3(0, 0, 0);
8623
+
8624
+ if(pbrMaterial.unlit){
8625
+ color.rgb = baseColor.rgb;
8626
+ }
8627
+ else{
8628
+ // Metallic and Roughness material properties are packed together
8629
+ // In glTF, these factors can be specified by fixed scalar values
8630
+ // or from a metallic-roughness map
8631
+ float perceptualRoughness = pbrMaterial.metallicRoughnessValues.y;
8632
+ float metallic = pbrMaterial.metallicRoughnessValues.x;
8633
+ #ifdef HAS_METALROUGHNESSMAP
8634
+ // Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel.
8635
+ // This layout intentionally reserves the 'r' channel for (optional) occlusion map data
8636
+ vec4 mrSample = texture(pbr_metallicRoughnessSampler, pbr_vUV);
8637
+ perceptualRoughness = mrSample.g * perceptualRoughness;
8638
+ metallic = mrSample.b * metallic;
8639
+ #endif
8640
+ perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);
8641
+ metallic = clamp(metallic, 0.0, 1.0);
8642
+ // Roughness is authored as perceptual roughness; as is convention,
8643
+ // convert to material roughness by squaring the perceptual roughness [2].
8644
+ float alphaRoughness = perceptualRoughness * perceptualRoughness;
8710
8645
 
8711
- v[0] = mul_fp64(a[0], b[0]);
8712
- v[1] = mul_fp64(a[1], b[1]);
8646
+ vec3 f0 = vec3(0.04);
8647
+ vec3 diffuseColor = baseColor.rgb * (vec3(1.0) - f0);
8648
+ diffuseColor *= 1.0 - metallic;
8649
+ vec3 specularColor = mix(f0, baseColor.rgb, metallic);
8713
8650
 
8714
- return sum_fp64(v[0], v[1]);
8715
- }
8651
+ // Compute reflectance.
8652
+ float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
8716
8653
 
8717
- // vec3 functions
8718
- void vec3_sub_fp64(vec2 a[3], vec2 b[3], out vec2 out_val[3]) {
8719
- for (int i = 0; i < 3; i++) {
8720
- out_val[i] = sum_fp64(a[i], b[i]);
8721
- }
8722
- }
8654
+ // For typical incident reflectance range (between 4% to 100%) set the grazing
8655
+ // reflectance to 100% for typical fresnel effect.
8656
+ // For very low reflectance range on highly diffuse objects (below 4%),
8657
+ // incrementally reduce grazing reflecance to 0%.
8658
+ float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);
8659
+ vec3 specularEnvironmentR0 = specularColor.rgb;
8660
+ vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90;
8723
8661
 
8724
- void vec3_sum_fp64(vec2 a[3], vec2 b[3], out vec2 out_val[3]) {
8725
- for (int i = 0; i < 3; i++) {
8726
- out_val[i] = sum_fp64(a[i], b[i]);
8727
- }
8728
- }
8662
+ vec3 n = getNormal(); // normal at surface point
8663
+ vec3 v = normalize(pbrProjection.camera - pbr_vPosition); // Vector from surface point to camera
8729
8664
 
8730
- vec2 vec3_length_fp64(vec2 x[3]) {
8731
- return sqrt_fp64(sum_fp64(sum_fp64(mul_fp64(x[0], x[0]), mul_fp64(x[1], x[1])),
8732
- mul_fp64(x[2], x[2])));
8733
- }
8665
+ float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
8666
+ vec3 reflection = -normalize(reflect(v, n));
8734
8667
 
8735
- vec2 vec3_distance_fp64(vec2 x[3], vec2 y[3]) {
8736
- vec2 diff[3];
8737
- vec3_sub_fp64(x, y, diff);
8738
- return vec3_length_fp64(diff);
8739
- }
8668
+ PBRInfo pbrInfo = PBRInfo(
8669
+ 0.0, // NdotL
8670
+ NdotV,
8671
+ 0.0, // NdotH
8672
+ 0.0, // LdotH
8673
+ 0.0, // VdotH
8674
+ perceptualRoughness,
8675
+ metallic,
8676
+ specularEnvironmentR0,
8677
+ specularEnvironmentR90,
8678
+ alphaRoughness,
8679
+ diffuseColor,
8680
+ specularColor,
8681
+ n,
8682
+ v
8683
+ );
8740
8684
 
8741
- // vec4 functions
8742
- void vec4_fp64(vec4 a, out vec2 out_val[4]) {
8743
- out_val[0].x = a[0];
8744
- out_val[0].y = 0.0;
8745
8685
 
8746
- out_val[1].x = a[1];
8747
- out_val[1].y = 0.0;
8686
+ #ifdef USE_LIGHTS
8687
+ // Apply ambient light
8688
+ PBRInfo_setAmbientLight(pbrInfo);
8689
+ color += calculateFinalColor(pbrInfo, lighting.ambientColor);
8748
8690
 
8749
- out_val[2].x = a[2];
8750
- out_val[2].y = 0.0;
8691
+ // Apply directional light
8692
+ for(int i = 0; i < lighting.directionalLightCount; i++) {
8693
+ if (i < lighting.directionalLightCount) {
8694
+ PBRInfo_setDirectionalLight(pbrInfo, lighting_getDirectionalLight(i).direction);
8695
+ color += calculateFinalColor(pbrInfo, lighting_getDirectionalLight(i).color);
8696
+ }
8697
+ }
8751
8698
 
8752
- out_val[3].x = a[3];
8753
- out_val[3].y = 0.0;
8754
- }
8699
+ // Apply point light
8700
+ for(int i = 0; i < lighting.pointLightCount; i++) {
8701
+ if (i < lighting.pointLightCount) {
8702
+ PBRInfo_setPointLight(pbrInfo, lighting_getPointLight(i));
8703
+ float attenuation = getPointLightAttenuation(lighting_getPointLight(i), distance(lighting_getPointLight(i).position, pbr_vPosition));
8704
+ color += calculateFinalColor(pbrInfo, lighting_getPointLight(i).color / attenuation);
8705
+ }
8706
+ }
8707
+ #endif
8755
8708
 
8756
- void vec4_scalar_mul_fp64(vec2 a[4], vec2 b, out vec2 out_val[4]) {
8757
- out_val[0] = mul_fp64(a[0], b);
8758
- out_val[1] = mul_fp64(a[1], b);
8759
- out_val[2] = mul_fp64(a[2], b);
8760
- out_val[3] = mul_fp64(a[3], b);
8761
- }
8709
+ // Calculate lighting contribution from image based lighting source (IBL)
8710
+ #ifdef USE_IBL
8711
+ if (pbrMaterial.IBLenabled) {
8712
+ color += getIBLContribution(pbrInfo, n, reflection);
8713
+ }
8714
+ #endif
8762
8715
 
8763
- void vec4_sum_fp64(vec2 a[4], vec2 b[4], out vec2 out_val[4]) {
8764
- for (int i = 0; i < 4; i++) {
8765
- out_val[i] = sum_fp64(a[i], b[i]);
8766
- }
8767
- }
8716
+ // Apply optional PBR terms for additional (optional) shading
8717
+ #ifdef HAS_OCCLUSIONMAP
8718
+ if (pbrMaterial.occlusionMapEnabled) {
8719
+ float ao = texture(pbr_occlusionSampler, pbr_vUV).r;
8720
+ color = mix(color, color * ao, pbrMaterial.occlusionStrength);
8721
+ }
8722
+ #endif
8768
8723
 
8769
- void vec4_dot_fp64(vec2 a[4], vec2 b[4], out vec2 out_val) {
8770
- vec2 v[4];
8724
+ #ifdef HAS_EMISSIVEMAP
8725
+ if (pbrMaterial.emissiveMapEnabled) {
8726
+ vec3 emissive = SRGBtoLINEAR(texture(pbr_emissiveSampler, pbr_vUV)).rgb * pbrMaterial.emissiveFactor;
8727
+ color += emissive;
8728
+ }
8729
+ #endif
8771
8730
 
8772
- v[0] = mul_fp64(a[0], b[0]);
8773
- v[1] = mul_fp64(a[1], b[1]);
8774
- v[2] = mul_fp64(a[2], b[2]);
8775
- v[3] = mul_fp64(a[3], b[3]);
8731
+ // This section uses mix to override final color for reference app visualization
8732
+ // of various parameters in the lighting equation.
8733
+ #ifdef PBR_DEBUG
8734
+ // TODO: Figure out how to debug multiple lights
8776
8735
 
8777
- out_val = sum_fp64(sum_fp64(v[0], v[1]), sum_fp64(v[2], v[3]));
8778
- }
8736
+ // color = mix(color, F, pbr_scaleFGDSpec.x);
8737
+ // color = mix(color, vec3(G), pbr_scaleFGDSpec.y);
8738
+ // color = mix(color, vec3(D), pbr_scaleFGDSpec.z);
8739
+ // color = mix(color, specContrib, pbr_scaleFGDSpec.w);
8779
8740
 
8780
- void mat4_vec4_mul_fp64(vec2 b[16], vec2 a[4], out vec2 out_val[4]) {
8781
- vec2 tmp[4];
8741
+ // color = mix(color, diffuseContrib, pbr_scaleDiffBaseMR.x);
8742
+ color = mix(color, baseColor.rgb, pbrMaterial.scaleDiffBaseMR.y);
8743
+ color = mix(color, vec3(metallic), pbrMaterial.scaleDiffBaseMR.z);
8744
+ color = mix(color, vec3(perceptualRoughness), pbrMaterial.scaleDiffBaseMR.w);
8745
+ #endif
8782
8746
 
8783
- for (int i = 0; i < 4; i++)
8784
- {
8785
- for (int j = 0; j < 4; j++)
8786
- {
8787
- tmp[j] = b[j + i * 4];
8788
- }
8789
- vec4_dot_fp64(a, tmp, out_val[i]);
8790
8747
  }
8748
+
8749
+ return vec4(pow(color,vec3(1.0/2.2)), baseColor.a);
8791
8750
  }
8792
8751
  `
8793
8752
  );
8794
8753
 
8795
- // src/modules-webgl1/math/fp64/fp64.ts
8796
- var CONST_UNIFORMS = {
8797
- // Used in LUMA_FP64_CODE_ELIMINATION_WORKAROUND
8798
- ONE: 1
8799
- };
8800
- function getUniforms4() {
8801
- return CONST_UNIFORMS;
8802
- }
8803
- var fp64arithmetic = {
8804
- name: "fp64-arithmetic",
8805
- vs: fp64arithmeticShader,
8806
- getUniforms: getUniforms4,
8807
- fp64ify,
8808
- fp64LowPart,
8809
- fp64ifyMatrix4
8754
+ // src/modules/lighting/pbr-material/pbr-projection.ts
8755
+ var uniformBlock = (
8756
+ /* glsl */
8757
+ `uniform pbrProjectionUniforms {
8758
+ mat4 modelViewProjectionMatrix;
8759
+ mat4 modelMatrix;
8760
+ mat4 normalMatrix;
8761
+ vec3 camera;
8762
+ } pbrProjection;
8763
+ `
8764
+ );
8765
+ var pbrProjection = {
8766
+ name: "pbrProjection",
8767
+ vs: uniformBlock,
8768
+ fs: uniformBlock,
8769
+ // TODO why is this needed?
8770
+ getUniforms: (props) => props,
8771
+ uniformTypes: {
8772
+ modelViewProjectionMatrix: "mat4x4<f32>",
8773
+ modelMatrix: "mat4x4<f32>",
8774
+ normalMatrix: "mat4x4<f32>",
8775
+ camera: "vec3<i32>"
8776
+ }
8810
8777
  };
8811
- var fp64 = {
8812
- name: "fp64",
8813
- vs: fp64functionShader,
8814
- dependencies: [fp64arithmetic],
8815
- // Additional Functions
8816
- fp64ify,
8817
- fp64LowPart,
8818
- fp64ifyMatrix4
8778
+
8779
+ // src/modules/lighting/pbr-material/pbr-material.ts
8780
+ var pbrMaterial = {
8781
+ props: {},
8782
+ uniforms: {},
8783
+ name: "pbrMaterial",
8784
+ dependencies: [lighting, pbrProjection],
8785
+ vs: vs2,
8786
+ fs: fs3,
8787
+ defines: {
8788
+ LIGHTING_FRAGMENT: 1
8789
+ // TODO defining these as 0 breaks shader
8790
+ // HAS_NORMALMAP: 0
8791
+ // HAS_EMISSIVEMAP: 0,
8792
+ // HAS_OCCLUSIONMAP: 0,
8793
+ // HAS_BASECOLORMAP: 0,
8794
+ // HAS_METALROUGHNESSMAP: 0,
8795
+ // ALPHA_CUTOFF: 0
8796
+ // USE_IBL: 0
8797
+ // PBR_DEBUG: 0
8798
+ },
8799
+ getUniforms: (props) => props,
8800
+ uniformTypes: {
8801
+ // Material is unlit
8802
+ unlit: "i32",
8803
+ // Base color map
8804
+ baseColorMapEnabled: "i32",
8805
+ baseColorFactor: "vec4<f32>",
8806
+ normalMapEnabled: "i32",
8807
+ normalScale: "f32",
8808
+ // #ifdef HAS_NORMALMAP
8809
+ emissiveMapEnabled: "i32",
8810
+ emissiveFactor: "vec3<f32>",
8811
+ // #ifdef HAS_EMISSIVEMAP
8812
+ metallicRoughnessValues: "vec2<f32>",
8813
+ metallicRoughnessMapEnabled: "i32",
8814
+ occlusionMapEnabled: "i32",
8815
+ occlusionStrength: "f32",
8816
+ // #ifdef HAS_OCCLUSIONMAP
8817
+ alphaCutoffEnabled: "i32",
8818
+ alphaCutoff: "f32",
8819
+ // #ifdef ALPHA_CUTOFF
8820
+ // IBL
8821
+ IBLenabled: "i32",
8822
+ scaleIBLAmbient: "vec2<f32>",
8823
+ // #ifdef USE_IBL
8824
+ // debugging flags used for shader output of intermediate PBR variables
8825
+ // #ifdef PBR_DEBUG
8826
+ scaleDiffBaseMR: "vec4<f32>",
8827
+ scaleFGDSpec: "vec4<f32>"
8828
+ }
8819
8829
  };
8820
8830
 
8821
8831
  // src/modules-webgl1/geometry/geometry.ts
@@ -8865,7 +8875,7 @@ vec3 geometry_getNormal() {
8865
8875
  projectionMatrix: IDENTITY_MATRIX2,
8866
8876
  cameraPositionWorld: [0, 0, 0]
8867
8877
  };
8868
- function getUniforms5(opts = DEFAULT_MODULE_OPTIONS, prevUniforms = {}) {
8878
+ function getUniforms4(opts = DEFAULT_MODULE_OPTIONS, prevUniforms = {}) {
8869
8879
  const uniforms = {};
8870
8880
  if (opts.modelMatrix !== void 0) {
8871
8881
  uniforms.modelMatrix = opts.modelMatrix;
@@ -8958,7 +8968,7 @@ vec4 project_to_clipspace(vec3 position) {
8958
8968
  ${common}`;
8959
8969
  var project = {
8960
8970
  name: "project",
8961
- getUniforms: getUniforms5,
8971
+ getUniforms: getUniforms4,
8962
8972
  vs: vs4,
8963
8973
  fs: fs5
8964
8974
  };
@@ -9039,7 +9049,7 @@ float getPointLightAttenuation(PointLight pointLight, float distance) {
9039
9049
  lightSourceUniforms.lighting_uDirectionalLightCount = directionalLights.length;
9040
9050
  return lightSourceUniforms;
9041
9051
  }
9042
- function getUniforms6(opts = INITIAL_MODULE_OPTIONS) {
9052
+ function getUniforms5(opts = INITIAL_MODULE_OPTIONS) {
9043
9053
  if ("lightSources" in opts) {
9044
9054
  const { ambientLight, pointLights, directionalLights } = opts.lightSources || {};
9045
9055
  const hasLights = ambientLight || pointLights && pointLights.length > 0 || directionalLights && directionalLights.length > 0;
@@ -9070,7 +9080,7 @@ float getPointLightAttenuation(PointLight pointLight, float distance) {
9070
9080
  default:
9071
9081
  }
9072
9082
  }
9073
- return getUniforms6({ lightSources });
9083
+ return getUniforms5({ lightSources });
9074
9084
  }
9075
9085
  return {};
9076
9086
  }
@@ -9078,7 +9088,7 @@ float getPointLightAttenuation(PointLight pointLight, float distance) {
9078
9088
  name: "lights",
9079
9089
  vs: lightingShader,
9080
9090
  fs: lightingShader,
9081
- getUniforms: getUniforms6,
9091
+ getUniforms: getUniforms5,
9082
9092
  defines: {
9083
9093
  MAX_LIGHTS: 3
9084
9094
  }
@@ -9088,7 +9098,7 @@ float getPointLightAttenuation(PointLight pointLight, float distance) {
9088
9098
  var DEFAULT_MODULE_OPTIONS2 = {
9089
9099
  lightDirection: new Float32Array([1, 1, 2])
9090
9100
  };
9091
- function getUniforms7(opts = DEFAULT_MODULE_OPTIONS2) {
9101
+ function getUniforms6(opts = DEFAULT_MODULE_OPTIONS2) {
9092
9102
  const uniforms = {};
9093
9103
  if (opts.lightDirection) {
9094
9104
  uniforms.dirlight_uLightDirection = opts.lightDirection;
@@ -9113,7 +9123,7 @@ vec4 dirlight_filterColor(vec4 color) {
9113
9123
  name: "dirlight",
9114
9124
  // vs // TODO - reuse normal from geometry module
9115
9125
  fs: fs6,
9116
- getUniforms: getUniforms7,
9126
+ getUniforms: getUniforms6,
9117
9127
  dependencies: [project]
9118
9128
  };
9119
9129
 
@@ -9207,7 +9217,7 @@ vec3 lighting_getSpecularLightColor(vec3 cameraPosition, vec3 position_worldspac
9207
9217
  lighting_uSpecularColor: specularColor.map((x) => x / 255)
9208
9218
  };
9209
9219
  }
9210
- function getUniforms8(opts = INITIAL_MODULE_OPTIONS2) {
9220
+ function getUniforms7(opts = INITIAL_MODULE_OPTIONS2) {
9211
9221
  if (!("material" in opts)) {
9212
9222
  return {};
9213
9223
  }
@@ -9224,7 +9234,7 @@ vec3 lighting_getSpecularLightColor(vec3 cameraPosition, vec3 position_worldspac
9224
9234
  defines: {
9225
9235
  LIGHTING_VERTEX: 1
9226
9236
  },
9227
- getUniforms: getUniforms8
9237
+ getUniforms: getUniforms7
9228
9238
  };
9229
9239
  var phongLighting = {
9230
9240
  name: "phong-lighting",
@@ -9233,7 +9243,7 @@ vec3 lighting_getSpecularLightColor(vec3 cameraPosition, vec3 position_worldspac
9233
9243
  defines: {
9234
9244
  LIGHTING_FRAGMENT: 1
9235
9245
  },
9236
- getUniforms: getUniforms8
9246
+ getUniforms: getUniforms7
9237
9247
  };
9238
9248
 
9239
9249
  // src/modules-webgl1/lighting/pbr/pbr-vertex-glsl.ts