@react-three/drei 9.52.2 → 9.52.4

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/README.md CHANGED
@@ -1830,6 +1830,8 @@ Enable shadows using the `castShadow` and `recieveShadow` prop.
1830
1830
  />
1831
1831
  ```
1832
1832
 
1833
+ > Note: Html 'blending' mode only correctly occludes rectangular HTML elements by default. Use the `geometry` prop to swap the backing geometry to a custom one if your Html has a different shape.
1834
+
1833
1835
  #### CycleRaycast
1834
1836
 
1835
1837
  ![](https://img.shields.io/badge/-Dom only-red)
@@ -2841,6 +2843,8 @@ export type Props = JSX.IntrinsicElements['group'] & {
2841
2843
  left?: boolean
2842
2844
  front?: boolean
2843
2845
  back?: boolean
2846
+ /** Disable all axes */
2847
+ disable?: boolean
2844
2848
  /** Disable x-axis centering */
2845
2849
  disableX?: boolean
2846
2850
  /** Disable y-axis centering */
@@ -3117,13 +3121,16 @@ Caustics are swirls of light that appear when light passes through transmissive
3117
3121
 
3118
3122
  ```tsx
3119
3123
  type CausticsProps = JSX.IntrinsicElements['group'] & {
3124
+ /** How many frames it will render, set it to Infinity for runtime, default: 1 */
3125
+ frames?: number
3120
3126
  /** Enables visual cues to help you stage your scene, default: false */
3121
3127
  debug?: boolean
3122
3128
  /** Will display caustics only and skip the models, default: false */
3123
3129
  causticsOnly: boolean
3124
3130
  /** Will include back faces and enable the backfaceIor prop, default: false */
3125
3131
  backfaces: boolean
3126
- /** The size of the camera frustum, default: 2 */
3132
+ /** The size of the camera frustum, make sure it fits your model perfectly
3133
+ * (with the debug flag)! The better it fits the more resolution you have. default: 2 */
3127
3134
  frustum?: number
3128
3135
  /** The IOR refraction index, default: 1.1 */
3129
3136
  ior?: number
@@ -3141,10 +3148,8 @@ type CausticsProps = JSX.IntrinsicElements['group'] & {
3141
3148
  near?: number
3142
3149
  /** Camera far, default: 100 */
3143
3150
  far?: number
3144
- /** Camera position, default: [5, 5, 5] */
3151
+ /** Camera position, it will point towards the contents bounds center, default: [5, 5, 5] */
3145
3152
  lightSource?: [x: number, y: number, z: number]
3146
- /** Camera lookAt, default: [0, 0, 0] */
3147
- focus?: [x: number, y: number, z: number]
3148
3153
  }
3149
3154
  ```
3150
3155
 
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),r=require("three"),n=require("react"),t=require("@react-three/fiber"),i=require("./useFBO.cjs.js"),o=require("./useHelper.cjs.js"),a=require("./shaderMaterial.cjs.js"),l=require("three-stdlib");function c(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function s(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach((function(n){if("default"!==n){var t=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(r,n,t.get?t:{enumerable:!0,get:function(){return e[n]}})}})),r.default=e,Object.freeze(r)}var u=c(e),d=s(r),v=s(n);function f(e=d.FrontSide){const r={value:new d.Matrix4};return Object.assign(new d.MeshNormalMaterial({side:e}),{viewMatrix:r,onBeforeCompile:e=>{e.uniforms.viewMatrix=r,e.fragmentShader="vec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n return normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n }\n"+e.fragmentShader.replace("#include <normal_fragment_maps>","#include <normal_fragment_maps>\n normal = inverseTransformDirection( normal, viewMatrix );\n")}})}const p=a.shaderMaterial({causticsTexture:null,causticsTextureB:null,color:new d.Color("white"),lightProjMatrix:new d.Matrix4,lightViewMatrix:new d.Matrix4},"varying vec3 vWorldPosition; \n void main() {\n gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.);\n vec4 worldPosition = modelMatrix * vec4(position, 1.);\n vWorldPosition = worldPosition.xyz;\n }","varying vec3 vWorldPosition;\n uniform vec3 color;\n uniform sampler2D causticsTexture; \n uniform sampler2D causticsTextureB; \n uniform mat4 lightProjMatrix;\n uniform mat4 lightViewMatrix;\n void main() {\n // Apply caustics \n vec4 lightSpacePos = lightProjMatrix * lightViewMatrix * vec4(vWorldPosition, 1.0);\n lightSpacePos.xyz /= lightSpacePos.w;\n lightSpacePos.xyz = lightSpacePos.xyz * 0.5 + 0.5; \n vec3 front = texture2D(causticsTexture, lightSpacePos.xy).rgb;\n vec3 back = texture2D(causticsTextureB, lightSpacePos.xy).rgb;\n gl_FragColor = vec4((front + back) * color, 1.0);\n #include <tonemapping_fragment>\n #include <encodings_fragment>\n }"),m=a.shaderMaterial({cameraMatrixWorld:new d.Matrix4,cameraProjectionMatrixInv:new d.Matrix4,normalTexture:null,depthTexture:null,lightDir:new d.Vector3(0,1,0),near:.1,far:100,modelMatrix:new d.Matrix4,worldRadius:1/40,ior:1.1,bounces:0,resolution:1024,size:10,intensity:.5},"\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n }"," \n uniform mat4 cameraMatrixWorld;\n uniform mat4 cameraProjectionMatrixInv;\n uniform vec3 lightDir;\n uniform float near;\n uniform float far;\n uniform float time;\n uniform float worldRadius;\n uniform float resolution;\n uniform float size;\n uniform float intensity;\n uniform float ior;\n precision highp isampler2D;\n precision highp usampler2D;\n uniform sampler2D normalTexture;\n uniform sampler2D depthTexture;\n uniform float bounces;\n varying vec2 vUv;\n vec3 WorldPosFromDepth(float depth, vec2 coord) {\n float z = depth * 2.0 - 1.0;\n vec4 clipSpacePosition = vec4(coord * 2.0 - 1.0, z, 1.0);\n vec4 viewSpacePosition = cameraProjectionMatrixInv * clipSpacePosition;\n // Perspective division\n viewSpacePosition /= viewSpacePosition.w;\n vec4 worldSpacePosition = cameraMatrixWorld * viewSpacePosition;\n return worldSpacePosition.xyz;\n } \n float sdPlane( vec3 p, vec3 n, float h ) {\n // n must be normalized\n return dot(p,n) + h;\n }\n float planeIntersect( vec3 ro, vec3 rd, vec4 p ) {\n return -(dot(ro,p.xyz)+p.w)/dot(rd,p.xyz);\n }\n vec3 totalInternalReflection(vec3 ro, vec3 rd, vec3 pos, vec3 normal, float ior, out vec3 rayOrigin, out vec3 rayDirection) {\n rayOrigin = ro;\n rayDirection = rd;\n rayDirection = refract(rayDirection, normal, 1.0 / ior);\n rayOrigin = pos + rayDirection * 0.1;\n return rayDirection;\n }\n void main() {\n // Each sample consists of random offset in the x and y direction\n float caustic = 0.0;\n float causticTexelSize = (1.0 / resolution) * size * 2.0;\n float texelsNeeded = worldRadius / causticTexelSize;\n float sampleRadius = texelsNeeded / resolution;\n float sum = 0.0;\n if (texture2D(depthTexture, vUv).x == 1.0) {\n gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n return;\n }\n vec2 offset1 = vec2(-0.5, -0.5);//vec2(rand() - 0.5, rand() - 0.5);\n vec2 offset2 = vec2(-0.5, 0.5);//vec2(rand() - 0.5, rand() - 0.5);\n vec2 offset3 = vec2(0.5, 0.5);//vec2(rand() - 0.5, rand() - 0.5);\n vec2 offset4 = vec2(0.5, -0.5);//vec2(rand() - 0.5, rand() - 0.5);\n vec2 uv1 = vUv + offset1 * sampleRadius;\n vec2 uv2 = vUv + offset2 * sampleRadius;\n vec2 uv3 = vUv + offset3 * sampleRadius;\n vec2 uv4 = vUv + offset4 * sampleRadius;\n vec3 normal1 = texture2D(normalTexture, uv1, -10.0).rgb * 2.0 - 1.0;\n vec3 normal2 = texture2D(normalTexture, uv2, -10.0).rgb * 2.0 - 1.0;\n vec3 normal3 = texture2D(normalTexture, uv3, -10.0).rgb * 2.0 - 1.0;\n vec3 normal4 = texture2D(normalTexture, uv4, -10.0).rgb * 2.0 - 1.0;\n float depth1 = texture2D(depthTexture, uv1, -10.0).x;\n float depth2 = texture2D(depthTexture, uv2, -10.0).x;\n float depth3 = texture2D(depthTexture, uv3, -10.0).x;\n float depth4 = texture2D(depthTexture, uv4, -10.0).x;\n // Sanity check the depths\n if (depth1 == 1.0 || depth2 == 1.0 || depth3 == 1.0 || depth4 == 1.0) {\n gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n return;\n }\n vec3 pos1 = WorldPosFromDepth(depth1, uv1);\n vec3 pos2 = WorldPosFromDepth(depth2, uv2);\n vec3 pos3 = WorldPosFromDepth(depth3, uv3);\n vec3 pos4 = WorldPosFromDepth(depth4, uv4);\n vec3 originPos1 = WorldPosFromDepth(0.0, uv1);\n vec3 originPos2 = WorldPosFromDepth(0.0, uv2);\n vec3 originPos3 = WorldPosFromDepth(0.0, uv3);\n vec3 originPos4 = WorldPosFromDepth(0.0, uv4);\n vec3 endPos1, endPos2, endPos3, endPos4;\n vec3 endDir1, endDir2, endDir3, endDir4;\n totalInternalReflection(originPos1, lightDir, pos1, normal1, ior, endPos1, endDir1);\n totalInternalReflection(originPos2, lightDir, pos2, normal2, ior, endPos2, endDir2);\n totalInternalReflection(originPos3, lightDir, pos3, normal3, ior, endPos3, endDir3);\n totalInternalReflection(originPos4, lightDir, pos4, normal4, ior, endPos4, endDir4);\n float lightPosArea = length(cross(originPos2 - originPos1, originPos3 - originPos1)) + length(cross(originPos3 - originPos1, originPos4 - originPos1));\n float t1 = planeIntersect(endPos1, endDir1, vec4(0.0, 1.0, 0.0, 0.0));\n float t2 = planeIntersect(endPos2, endDir2, vec4(0.0, 1.0, 0.0, 0.0));\n float t3 = planeIntersect(endPos3, endDir3, vec4(0.0, 1.0, 0.0, 0.0));\n float t4 = planeIntersect(endPos4, endDir4, vec4(0.0, 1.0, 0.0, 0.0));\n vec3 finalPos1 = endPos1 + endDir1 * t1;\n vec3 finalPos2 = endPos2 + endDir2 * t2;\n vec3 finalPos3 = endPos3 + endDir3 * t3;\n vec3 finalPos4 = endPos4 + endDir4 * t4;\n float finalArea = length(cross(finalPos2 - finalPos1, finalPos3 - finalPos1)) + length(cross(finalPos3 - finalPos1, finalPos4 - finalPos1));\n caustic += intensity * (lightPosArea / finalArea);\n // Calculate the area of the triangle in light spaces\n gl_FragColor = vec4(vec3(max(caustic, 0.0)), 1.0);\n }"),x={depth:!0,minFilter:d.LinearFilter,magFilter:d.LinearFilter,encoding:d.LinearEncoding,type:d.UnsignedByteType},g={minFilter:d.LinearMipmapLinearFilter,magFilter:d.LinearFilter,encoding:d.LinearEncoding,format:d.RGBAFormat,type:d.FloatType,generateMipmaps:!0},h=v.forwardRef((({debug:e,children:r,frustum:n=2,ior:a=1.1,color:c="white",causticsOnly:s=!1,backfaces:h=!1,backfaceIor:P=1.1,worldRadius:D=.3125,intensity:M=.05,resolution:y=2024,near:w=.1,far:T=100,lightSource:b=[5,5,5],focus:F=[0,0,0],...S},j)=>{t.extend({CausticsProjectionMaterial:p});const R=v.useRef(null),W=v.useRef(null),z=v.useRef(null),I=v.useRef(null),O=t.useThree((e=>e.gl)),_=o.useHelper(e&&W,d.CameraHelper),B=o.useHelper(e&&I,d.BoxHelper),C=i.useFBO(y,y,x),E=i.useFBO(y,y,x),U=i.useFBO(y,y,g),k=i.useFBO(y,y,g),[q]=v.useState((()=>f())),[A]=v.useState((()=>f(d.BackSide))),[L]=v.useState((()=>new m)),[V]=v.useState((()=>new l.FullScreenQuad(L))),H=new d.Vector3;return v.useLayoutEffect((()=>{var r,t;(R.current.updateWorldMatrix(!1,!0),W.current.position.set(...b),W.current.lookAt(...F),W.current.updateWorldMatrix(!1,!1),W.current.updateProjectionMatrix(),e)&&(null==(r=_.current)||r.update(),null==(t=B.current)||t.update());A.viewMatrix.value=q.viewMatrix.value=W.current.matrixWorldInverse,L.cameraMatrixWorld=W.current.matrixWorld,L.cameraProjectionMatrixInv=W.current.projectionMatrixInverse,L.lightDir=W.current.getWorldPosition(H).normalize().multiplyScalar(-1),L.near=W.current.near,L.far=W.current.far,L.resolution=y,L.size=n,L.intensity=M,L.worldRadius=D,z.current.visible=!0,O.setRenderTarget(C),O.clear(),z.current.overrideMaterial=q,O.render(z.current,W.current),O.setRenderTarget(E),O.clear(),h&&(z.current.overrideMaterial=A,O.render(z.current,W.current)),z.current.overrideMaterial=null,L.ior=a,I.current.material.lightProjMatrix=W.current.projectionMatrix,I.current.material.lightViewMatrix=W.current.matrixWorldInverse,L.normalTexture=C.texture,L.depthTexture=C.depthTexture,O.setRenderTarget(U),O.clear(),V.render(O),L.ior=P,L.normalTexture=E.texture,L.depthTexture=E.depthTexture,O.setRenderTarget(k),O.clear(),h&&V.render(O),O.setRenderTarget(null),s&&(z.current.visible=!1)})),v.createElement("group",u.default({ref:R},S),v.createElement("orthographicCamera",{ref:W,up:[0,1,0],left:-n,right:n,top:n,bottom:-n,near:w,far:T}),v.createElement("scene",{ref:z},r),v.createElement("mesh",{ref:I,"rotation-x":-Math.PI/2,scale:2*n},v.createElement("planeGeometry",null),v.createElement("causticsProjectionMaterial",{transparent:!0,color:c,causticsTexture:U.texture,causticsTextureB:k.texture,blending:d.CustomBlending,blendSrc:d.OneFactor,blendDst:d.SrcAlphaFactor,depthWrite:!1})))}));exports.Caustics=h;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),r=require("three"),n=require("react"),t=require("@react-three/fiber"),o=require("./useFBO.cjs.js"),i=require("./useHelper.cjs.js"),a=require("./shaderMaterial.cjs.js"),l=require("./Edges.cjs.js"),c=require("three-stdlib");function s(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function u(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach((function(n){if("default"!==n){var t=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(r,n,t.get?t:{enumerable:!0,get:function(){return e[n]}})}})),r.default=e,Object.freeze(r)}var d=s(e),m=u(r),p=u(n);function v(e=m.FrontSide){const r={value:new m.Matrix4};return Object.assign(new m.MeshNormalMaterial({side:e}),{viewMatrix:r,onBeforeCompile:e=>{e.uniforms.viewMatrix=r,e.fragmentShader="vec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n return normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n }\n"+e.fragmentShader.replace("#include <normal_fragment_maps>","#include <normal_fragment_maps>\n normal = inverseTransformDirection( normal, viewMatrix );\n")}})}const f=a.shaderMaterial({causticsTexture:null,causticsTextureB:null,color:new m.Color,lightProjMatrix:new m.Matrix4,lightViewMatrix:new m.Matrix4},"varying vec3 vWorldPosition; \n void main() {\n gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.);\n vec4 worldPosition = modelMatrix * vec4(position, 1.);\n vWorldPosition = worldPosition.xyz;\n }","varying vec3 vWorldPosition;\n uniform vec3 color;\n uniform sampler2D causticsTexture; \n uniform sampler2D causticsTextureB; \n uniform mat4 lightProjMatrix;\n uniform mat4 lightViewMatrix;\n void main() {\n // Apply caustics \n vec4 lightSpacePos = lightProjMatrix * lightViewMatrix * vec4(vWorldPosition, 1.0);\n lightSpacePos.xyz /= lightSpacePos.w;\n lightSpacePos.xyz = lightSpacePos.xyz * 0.5 + 0.5; \n vec3 front = texture2D(causticsTexture, lightSpacePos.xy).rgb;\n vec3 back = texture2D(causticsTextureB, lightSpacePos.xy).rgb;\n gl_FragColor = vec4((front + back) * color, 1.0);\n #include <tonemapping_fragment>\n #include <encodings_fragment>\n }"),x=a.shaderMaterial({cameraMatrixWorld:new m.Matrix4,cameraProjectionMatrixInv:new m.Matrix4,normalTexture:null,depthTexture:null,lightDir:new m.Vector3(0,1,0),lightPlaneNormal:new m.Vector3(0,1,0),lightPlaneConstant:0,near:.1,far:100,modelMatrix:new m.Matrix4,worldRadius:1/40,ior:1.1,bounces:0,resolution:1024,size:10,intensity:.5},"\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n }"," \n uniform mat4 cameraMatrixWorld;\n uniform mat4 cameraProjectionMatrixInv;\n uniform vec3 lightDir;\n uniform vec3 lightPlaneNormal;\n uniform float lightPlaneConstant;\n uniform float near;\n uniform float far;\n uniform float time;\n uniform float worldRadius;\n uniform float resolution;\n uniform float size;\n uniform float intensity;\n uniform float ior;\n precision highp isampler2D;\n precision highp usampler2D;\n uniform sampler2D normalTexture;\n uniform sampler2D depthTexture;\n uniform float bounces;\n varying vec2 vUv;\n vec3 WorldPosFromDepth(float depth, vec2 coord) {\n float z = depth * 2.0 - 1.0;\n vec4 clipSpacePosition = vec4(coord * 2.0 - 1.0, z, 1.0);\n vec4 viewSpacePosition = cameraProjectionMatrixInv * clipSpacePosition;\n // Perspective division\n viewSpacePosition /= viewSpacePosition.w;\n vec4 worldSpacePosition = cameraMatrixWorld * viewSpacePosition;\n return worldSpacePosition.xyz;\n } \n float sdPlane( vec3 p, vec3 n, float h ) {\n // n must be normalized\n return dot(p,n) + h;\n }\n float planeIntersect( vec3 ro, vec3 rd, vec4 p ) {\n return -(dot(ro,p.xyz)+p.w)/dot(rd,p.xyz);\n }\n vec3 totalInternalReflection(vec3 ro, vec3 rd, vec3 pos, vec3 normal, float ior, out vec3 rayOrigin, out vec3 rayDirection) {\n rayOrigin = ro;\n rayDirection = rd;\n rayDirection = refract(rayDirection, normal, 1.0 / ior);\n rayOrigin = pos + rayDirection * 0.1;\n return rayDirection;\n }\n void main() {\n // Each sample consists of random offset in the x and y direction\n float caustic = 0.0;\n float causticTexelSize = (1.0 / resolution) * size * 2.0;\n float texelsNeeded = worldRadius / causticTexelSize;\n float sampleRadius = texelsNeeded / resolution;\n float sum = 0.0;\n if (texture2D(depthTexture, vUv).x == 1.0) {\n gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n return;\n }\n vec2 offset1 = vec2(-0.5, -0.5);//vec2(rand() - 0.5, rand() - 0.5);\n vec2 offset2 = vec2(-0.5, 0.5);//vec2(rand() - 0.5, rand() - 0.5);\n vec2 offset3 = vec2(0.5, 0.5);//vec2(rand() - 0.5, rand() - 0.5);\n vec2 offset4 = vec2(0.5, -0.5);//vec2(rand() - 0.5, rand() - 0.5);\n vec2 uv1 = vUv + offset1 * sampleRadius;\n vec2 uv2 = vUv + offset2 * sampleRadius;\n vec2 uv3 = vUv + offset3 * sampleRadius;\n vec2 uv4 = vUv + offset4 * sampleRadius;\n vec3 normal1 = texture2D(normalTexture, uv1, -10.0).rgb * 2.0 - 1.0;\n vec3 normal2 = texture2D(normalTexture, uv2, -10.0).rgb * 2.0 - 1.0;\n vec3 normal3 = texture2D(normalTexture, uv3, -10.0).rgb * 2.0 - 1.0;\n vec3 normal4 = texture2D(normalTexture, uv4, -10.0).rgb * 2.0 - 1.0;\n float depth1 = texture2D(depthTexture, uv1, -10.0).x;\n float depth2 = texture2D(depthTexture, uv2, -10.0).x;\n float depth3 = texture2D(depthTexture, uv3, -10.0).x;\n float depth4 = texture2D(depthTexture, uv4, -10.0).x;\n // Sanity check the depths\n if (depth1 == 1.0 || depth2 == 1.0 || depth3 == 1.0 || depth4 == 1.0) {\n gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n return;\n }\n vec3 pos1 = WorldPosFromDepth(depth1, uv1);\n vec3 pos2 = WorldPosFromDepth(depth2, uv2);\n vec3 pos3 = WorldPosFromDepth(depth3, uv3);\n vec3 pos4 = WorldPosFromDepth(depth4, uv4);\n vec3 originPos1 = WorldPosFromDepth(0.0, uv1);\n vec3 originPos2 = WorldPosFromDepth(0.0, uv2);\n vec3 originPos3 = WorldPosFromDepth(0.0, uv3);\n vec3 originPos4 = WorldPosFromDepth(0.0, uv4);\n vec3 endPos1, endPos2, endPos3, endPos4;\n vec3 endDir1, endDir2, endDir3, endDir4;\n totalInternalReflection(originPos1, lightDir, pos1, normal1, ior, endPos1, endDir1);\n totalInternalReflection(originPos2, lightDir, pos2, normal2, ior, endPos2, endDir2);\n totalInternalReflection(originPos3, lightDir, pos3, normal3, ior, endPos3, endDir3);\n totalInternalReflection(originPos4, lightDir, pos4, normal4, ior, endPos4, endDir4);\n float lightPosArea = length(cross(originPos2 - originPos1, originPos3 - originPos1)) + length(cross(originPos3 - originPos1, originPos4 - originPos1));\n float t1 = planeIntersect(endPos1, endDir1, vec4(lightPlaneNormal, lightPlaneConstant));\n float t2 = planeIntersect(endPos2, endDir2, vec4(lightPlaneNormal, lightPlaneConstant));\n float t3 = planeIntersect(endPos3, endDir3, vec4(lightPlaneNormal, lightPlaneConstant));\n float t4 = planeIntersect(endPos4, endDir4, vec4(lightPlaneNormal, lightPlaneConstant));\n vec3 finalPos1 = endPos1 + endDir1 * t1;\n vec3 finalPos2 = endPos2 + endDir2 * t2;\n vec3 finalPos3 = endPos3 + endDir3 * t3;\n vec3 finalPos4 = endPos4 + endDir4 * t4;\n float finalArea = length(cross(finalPos2 - finalPos1, finalPos3 - finalPos1)) + length(cross(finalPos3 - finalPos1, finalPos4 - finalPos1));\n caustic += intensity * (lightPosArea / finalArea);\n // Calculate the area of the triangle in light spaces\n gl_FragColor = vec4(vec3(max(caustic, 0.0)), 1.0);\n }"),h={depth:!0,minFilter:m.LinearFilter,magFilter:m.LinearFilter,encoding:m.LinearEncoding,type:m.UnsignedByteType},g={minFilter:m.LinearMipmapLinearFilter,magFilter:m.LinearFilter,encoding:m.LinearEncoding,format:m.RGBAFormat,type:m.FloatType,generateMipmaps:!0},P=p.forwardRef((({debug:e,children:r,frames:n=1,ior:a=1.1,color:s="white",causticsOnly:u=!1,backfaces:P=!1,backfaceIor:y=1.1,worldRadius:M=.3125,intensity:w=.05,resolution:D=2024,near:T=.1,far:F=100,lightSource:S=[5,5,5],...b},j)=>{t.extend({CausticsProjectionMaterial:f});const z=p.useRef(null),R=p.useRef(null),W=p.useRef(null),C=p.useRef(null),I=t.useThree((e=>e.gl)),V=i.useHelper(e&&R,m.CameraHelper),O=o.useFBO(D,D,h),B=o.useFBO(D,D,h),_=o.useFBO(D,D,g),E=o.useFBO(D,D,g),[A]=p.useState((()=>v())),[N]=p.useState((()=>v(m.BackSide))),[k]=p.useState((()=>new x)),[q]=p.useState((()=>new c.FullScreenQuad(k)));p.useLayoutEffect((()=>{z.current.updateWorldMatrix(!0,!0)}),[]);let U=0;const L=new m.Vector3,H=new m.Frustum,G=new m.Matrix4,Q=new m.Plane,J=new m.Vector3,K=new m.Vector3,X=new m.Box3,Y=new m.Vector3;return t.useFrame(((r,t)=>{if(n===1/0||U++<n){var o,i;J.fromArray(S).normalize(),K.copy(J).multiplyScalar(-1);let r=[];null==(o=W.current.parent)||o.matrixWorld.identity(),X.setFromObject(W.current,!0),r.push(new m.Vector3(X.min.x,X.min.y,X.min.z)),r.push(new m.Vector3(X.min.x,X.min.y,X.max.z)),r.push(new m.Vector3(X.min.x,X.max.y,X.min.z)),r.push(new m.Vector3(X.min.x,X.max.y,X.max.z)),r.push(new m.Vector3(X.max.x,X.min.y,X.min.z)),r.push(new m.Vector3(X.max.x,X.min.y,X.max.z)),r.push(new m.Vector3(X.max.x,X.max.y,X.min.z)),r.push(new m.Vector3(X.max.x,X.max.y,X.max.z));const n=r.map((e=>e.clone()));X.getCenter(Y),r=r.map((e=>e.clone().sub(Y)));const t=Q.set(K,0),l=r.map((e=>t.projectPoint(e,new m.Vector3))),c=l.reduce(((e,r)=>e.add(r)),L.set(0,0,0)).divideScalar(l.length),s=l.map((e=>e.distanceTo(c))).reduce(((e,r)=>Math.max(e,r))),d=r.map((e=>e.dot(J))).reduce(((e,r)=>Math.max(e,r)));R.current.position.copy(J.clone().multiplyScalar(d).add(Y)),R.current.lookAt(W.current.localToWorld(Y.clone()));const p=G.lookAt(R.current.position,Y,L.set(0,1,0));R.current.left=-s,R.current.right=s,R.current.top=s,R.current.bottom=-s;const v=L.set(0,s,0).applyMatrix4(p),f=(R.current.position.y+v.y)/J.y;R.current.near=.1,R.current.far=f,R.current.updateProjectionMatrix(),R.current.updateMatrixWorld();const x=n.map((e=>e.add(J.clone().multiplyScalar(-e.y/J.y)))),h=x.reduce(((e,r)=>e.add(r)),L.set(0,0,0)).divideScalar(x.length),g=2*x.map((e=>Math.hypot(e.x-h.x,e.z-h.z))).reduce(((e,r)=>Math.max(e,r)));C.current.scale.setScalar(g),C.current.position.copy(h),e&&(null==(i=V.current)||i.update());const T=H.setFromProjectionMatrix(G.multiplyMatrices(R.current.projectionMatrix,R.current.matrixWorldInverse)).planes[4];N.viewMatrix.value=A.viewMatrix.value=R.current.matrixWorldInverse,k.cameraMatrixWorld=R.current.matrixWorld,k.cameraProjectionMatrixInv=R.current.projectionMatrixInverse,k.lightDir=K,k.lightPlaneNormal=T.normal,k.lightPlaneConstant=T.constant,k.near=R.current.near,k.far=R.current.far,k.resolution=D,k.size=s,k.intensity=w,k.worldRadius=M,W.current.visible=!0,I.setRenderTarget(O),I.clear(),W.current.overrideMaterial=A,I.render(W.current,R.current),I.setRenderTarget(B),I.clear(),P&&(W.current.overrideMaterial=N,I.render(W.current,R.current)),W.current.overrideMaterial=null,k.ior=a,C.current.material.lightProjMatrix=R.current.projectionMatrix,C.current.material.lightViewMatrix=R.current.matrixWorldInverse,k.normalTexture=O.texture,k.depthTexture=O.depthTexture,I.setRenderTarget(_),I.clear(),q.render(I),k.ior=y,k.normalTexture=B.texture,k.depthTexture=B.depthTexture,I.setRenderTarget(E),I.clear(),P&&q.render(I),I.setRenderTarget(null),u&&(W.current.visible=!1)}})),p.createElement("group",d.default({ref:z},b),p.createElement("orthographicCamera",{ref:R,up:[0,1,0]}),p.createElement("scene",{ref:W},r),p.createElement("mesh",{ref:C,"rotation-x":-Math.PI/2},p.createElement("planeGeometry",null),p.createElement("causticsProjectionMaterial",{transparent:!0,color:s,causticsTexture:_.texture,causticsTextureB:E.texture,blending:m.CustomBlending,blendSrc:m.OneFactor,blendDst:m.SrcAlphaFactor,depthWrite:!1}),e&&p.createElement(l.Edges,null,p.createElement("lineBasicMaterial",{color:"#ffff00",toneMapped:!1}))))}));exports.Caustics=P;
@@ -36,10 +36,10 @@ export declare const Caustics: React.ForwardRefExoticComponent<Pick<Omit<ReactTh
36
36
  layers?: ReactThreeFiber.Layers | undefined;
37
37
  dispose?: (() => void) | null | undefined;
38
38
  } & import("@react-three/fiber/dist/declarations/src/core/events").EventHandlers & {
39
+ frames?: number | undefined;
39
40
  debug?: boolean | undefined;
40
41
  causticsOnly: boolean;
41
42
  backfaces: boolean;
42
- frustum?: number | undefined;
43
43
  ior?: number | undefined;
44
44
  backfaceIor?: number | undefined;
45
45
  worldRadius?: number | undefined;
@@ -49,5 +49,4 @@ export declare const Caustics: React.ForwardRefExoticComponent<Pick<Omit<ReactTh
49
49
  near?: number | undefined;
50
50
  far?: number | undefined;
51
51
  lightSource?: [x: number, y: number, z: number] | undefined;
52
- focus?: [x: number, y: number, z: number] | undefined;
53
- }, "visible" | "attach" | "args" | "children" | "key" | "onUpdate" | "position" | "up" | "scale" | "rotation" | "matrix" | "quaternion" | "layers" | "dispose" | "type" | "isGroup" | "id" | "uuid" | "name" | "parent" | "modelViewMatrix" | "normalMatrix" | "matrixWorld" | "matrixAutoUpdate" | "matrixWorldNeedsUpdate" | "castShadow" | "receiveShadow" | "frustumCulled" | "renderOrder" | "animations" | "userData" | "customDepthMaterial" | "customDistanceMaterial" | "isObject3D" | "onBeforeRender" | "onAfterRender" | "applyMatrix4" | "applyQuaternion" | "setRotationFromAxisAngle" | "setRotationFromEuler" | "setRotationFromMatrix" | "setRotationFromQuaternion" | "rotateOnAxis" | "rotateOnWorldAxis" | "rotateX" | "rotateY" | "rotateZ" | "translateOnAxis" | "translateX" | "translateY" | "translateZ" | "localToWorld" | "worldToLocal" | "lookAt" | "add" | "remove" | "removeFromParent" | "clear" | "getObjectById" | "getObjectByName" | "getObjectByProperty" | "getWorldPosition" | "getWorldQuaternion" | "getWorldScale" | "getWorldDirection" | "raycast" | "traverse" | "traverseVisible" | "traverseAncestors" | "updateMatrix" | "updateMatrixWorld" | "updateWorldMatrix" | "toJSON" | "clone" | "copy" | "addEventListener" | "hasEventListener" | "removeEventListener" | "dispatchEvent" | "color" | keyof import("@react-three/fiber/dist/declarations/src/core/events").EventHandlers | "near" | "far" | "intensity" | "focus" | "ior" | "resolution" | "debug" | "frustum" | "worldRadius" | "causticsOnly" | "backfaces" | "backfaceIor" | "lightSource"> & React.RefAttributes<unknown>>;
52
+ }, "visible" | "attach" | "args" | "children" | "key" | "onUpdate" | "position" | "up" | "scale" | "rotation" | "matrix" | "quaternion" | "layers" | "dispose" | "type" | "isGroup" | "id" | "uuid" | "name" | "parent" | "modelViewMatrix" | "normalMatrix" | "matrixWorld" | "matrixAutoUpdate" | "matrixWorldNeedsUpdate" | "castShadow" | "receiveShadow" | "frustumCulled" | "renderOrder" | "animations" | "userData" | "customDepthMaterial" | "customDistanceMaterial" | "isObject3D" | "onBeforeRender" | "onAfterRender" | "applyMatrix4" | "applyQuaternion" | "setRotationFromAxisAngle" | "setRotationFromEuler" | "setRotationFromMatrix" | "setRotationFromQuaternion" | "rotateOnAxis" | "rotateOnWorldAxis" | "rotateX" | "rotateY" | "rotateZ" | "translateOnAxis" | "translateX" | "translateY" | "translateZ" | "localToWorld" | "worldToLocal" | "lookAt" | "add" | "remove" | "removeFromParent" | "clear" | "getObjectById" | "getObjectByName" | "getObjectByProperty" | "getWorldPosition" | "getWorldQuaternion" | "getWorldScale" | "getWorldDirection" | "raycast" | "traverse" | "traverseVisible" | "traverseAncestors" | "updateMatrix" | "updateMatrixWorld" | "updateWorldMatrix" | "toJSON" | "clone" | "copy" | "addEventListener" | "hasEventListener" | "removeEventListener" | "dispatchEvent" | "color" | keyof import("@react-three/fiber/dist/declarations/src/core/events").EventHandlers | "near" | "far" | "intensity" | "ior" | "resolution" | "debug" | "frames" | "worldRadius" | "causticsOnly" | "backfaces" | "backfaceIor" | "lightSource"> & React.RefAttributes<unknown>>;
package/core/Caustics.js CHANGED
@@ -1,10 +1,11 @@
1
1
  import _extends from '@babel/runtime/helpers/esm/extends';
2
2
  import * as THREE from 'three';
3
3
  import * as React from 'react';
4
- import { extend, useThree } from '@react-three/fiber';
4
+ import { extend, useThree, useFrame } from '@react-three/fiber';
5
5
  import { useFBO } from './useFBO.js';
6
6
  import { useHelper } from './useHelper.js';
7
7
  import { shaderMaterial } from './shaderMaterial.js';
8
+ import { Edges } from './Edges.js';
8
9
  import { FullScreenQuad } from 'three-stdlib';
9
10
 
10
11
  function createNormalMaterial(side = THREE.FrontSide) {
@@ -28,7 +29,7 @@ function createNormalMaterial(side = THREE.FrontSide) {
28
29
  const CausticsProjectionMaterial = shaderMaterial({
29
30
  causticsTexture: null,
30
31
  causticsTextureB: null,
31
- color: new THREE.Color('white'),
32
+ color: new THREE.Color(),
32
33
  lightProjMatrix: new THREE.Matrix4(),
33
34
  lightViewMatrix: new THREE.Matrix4()
34
35
  }, `varying vec3 vWorldPosition;
@@ -59,6 +60,8 @@ const CausticsMaterial = shaderMaterial({
59
60
  normalTexture: null,
60
61
  depthTexture: null,
61
62
  lightDir: new THREE.Vector3(0, 1, 0),
63
+ lightPlaneNormal: new THREE.Vector3(0, 1, 0),
64
+ lightPlaneConstant: 0,
62
65
  near: 0.1,
63
66
  far: 100,
64
67
  modelMatrix: new THREE.Matrix4(),
@@ -81,6 +84,8 @@ const CausticsMaterial = shaderMaterial({
81
84
  uniform mat4 cameraMatrixWorld;
82
85
  uniform mat4 cameraProjectionMatrixInv;
83
86
  uniform vec3 lightDir;
87
+ uniform vec3 lightPlaneNormal;
88
+ uniform float lightPlaneConstant;
84
89
  uniform float near;
85
90
  uniform float far;
86
91
  uniform float time;
@@ -165,10 +170,10 @@ const CausticsMaterial = shaderMaterial({
165
170
  totalInternalReflection(originPos3, lightDir, pos3, normal3, ior, endPos3, endDir3);
166
171
  totalInternalReflection(originPos4, lightDir, pos4, normal4, ior, endPos4, endDir4);
167
172
  float lightPosArea = length(cross(originPos2 - originPos1, originPos3 - originPos1)) + length(cross(originPos3 - originPos1, originPos4 - originPos1));
168
- float t1 = planeIntersect(endPos1, endDir1, vec4(0.0, 1.0, 0.0, 0.0));
169
- float t2 = planeIntersect(endPos2, endDir2, vec4(0.0, 1.0, 0.0, 0.0));
170
- float t3 = planeIntersect(endPos3, endDir3, vec4(0.0, 1.0, 0.0, 0.0));
171
- float t4 = planeIntersect(endPos4, endDir4, vec4(0.0, 1.0, 0.0, 0.0));
173
+ float t1 = planeIntersect(endPos1, endDir1, vec4(lightPlaneNormal, lightPlaneConstant));
174
+ float t2 = planeIntersect(endPos2, endDir2, vec4(lightPlaneNormal, lightPlaneConstant));
175
+ float t3 = planeIntersect(endPos3, endDir3, vec4(lightPlaneNormal, lightPlaneConstant));
176
+ float t4 = planeIntersect(endPos4, endDir4, vec4(lightPlaneNormal, lightPlaneConstant));
172
177
  vec3 finalPos1 = endPos1 + endDir1 * t1;
173
178
  vec3 finalPos2 = endPos2 + endDir2 * t2;
174
179
  vec3 finalPos3 = endPos3 + endDir3 * t3;
@@ -196,7 +201,7 @@ const CAUSTICPROPS = {
196
201
  const Caustics = /*#__PURE__*/React.forwardRef(({
197
202
  debug,
198
203
  children,
199
- frustum = 2,
204
+ frames = 1,
200
205
  ior = 1.1,
201
206
  color = 'white',
202
207
  causticsOnly = false,
@@ -208,7 +213,6 @@ const Caustics = /*#__PURE__*/React.forwardRef(({
208
213
  near = 0.1,
209
214
  far = 100,
210
215
  lightSource = [5, 5, 5],
211
- focus = [0, 0, 0],
212
216
  ...props
213
217
  }, fref) => {
214
218
  extend({
@@ -219,8 +223,7 @@ const Caustics = /*#__PURE__*/React.forwardRef(({
219
223
  const scene = React.useRef(null);
220
224
  const plane = React.useRef(null);
221
225
  const gl = useThree(state => state.gl);
222
- const helper = useHelper(debug && camera, THREE.CameraHelper);
223
- const boxHelper = useHelper(debug && plane, THREE.BoxHelper); // Buffers for front and back faces
226
+ const helper = useHelper(debug && camera, THREE.CameraHelper); // Buffers for front and back faces
224
227
 
225
228
  const normalTarget = useFBO(resolution, resolution, NORMALPROPS);
226
229
  const normalTargetB = useFBO(resolution, resolution, NORMALPROPS);
@@ -232,89 +235,130 @@ const Caustics = /*#__PURE__*/React.forwardRef(({
232
235
 
233
236
  const [causticsMaterial] = React.useState(() => new CausticsMaterial());
234
237
  const [causticsQuad] = React.useState(() => new FullScreenQuad(causticsMaterial));
235
- const pos = new THREE.Vector3();
236
238
  React.useLayoutEffect(() => {
237
- // Update matrix world and the camera
238
- ref.current.updateWorldMatrix(false, true);
239
- camera.current.position.set(...lightSource);
240
- camera.current.lookAt(...focus);
241
- camera.current.updateWorldMatrix(false, false);
242
- camera.current.updateProjectionMatrix();
239
+ // Update matrix world and the camera on first mount
240
+ ref.current.updateWorldMatrix(true, true);
241
+ }, []);
242
+ let count = 0;
243
+ const v = new THREE.Vector3();
244
+ const lpF = new THREE.Frustum();
245
+ const lpM = new THREE.Matrix4();
246
+ const lpP = new THREE.Plane();
247
+ const lightDir = new THREE.Vector3();
248
+ const lightDirInv = new THREE.Vector3();
249
+ const bounds = new THREE.Box3();
250
+ const focusPos = new THREE.Vector3();
251
+ useFrame((state, delta) => {
252
+ if (frames === Infinity || count++ < frames) {
253
+ var _scene$current$parent, _helper$current;
243
254
 
244
- if (debug) {
245
- var _helper$current, _boxHelper$current;
255
+ lightDir.fromArray(lightSource).normalize();
256
+ lightDirInv.copy(lightDir).multiplyScalar(-1);
257
+ let boundsVertices = [];
258
+ (_scene$current$parent = scene.current.parent) == null ? void 0 : _scene$current$parent.matrixWorld.identity();
259
+ bounds.setFromObject(scene.current, true);
260
+ boundsVertices.push(new THREE.Vector3(bounds.min.x, bounds.min.y, bounds.min.z));
261
+ boundsVertices.push(new THREE.Vector3(bounds.min.x, bounds.min.y, bounds.max.z));
262
+ boundsVertices.push(new THREE.Vector3(bounds.min.x, bounds.max.y, bounds.min.z));
263
+ boundsVertices.push(new THREE.Vector3(bounds.min.x, bounds.max.y, bounds.max.z));
264
+ boundsVertices.push(new THREE.Vector3(bounds.max.x, bounds.min.y, bounds.min.z));
265
+ boundsVertices.push(new THREE.Vector3(bounds.max.x, bounds.min.y, bounds.max.z));
266
+ boundsVertices.push(new THREE.Vector3(bounds.max.x, bounds.max.y, bounds.min.z));
267
+ boundsVertices.push(new THREE.Vector3(bounds.max.x, bounds.max.y, bounds.max.z));
268
+ const worldVerts = boundsVertices.map(v => v.clone());
269
+ bounds.getCenter(focusPos);
270
+ boundsVertices = boundsVertices.map(v => v.clone().sub(focusPos));
271
+ const lightPlane = lpP.set(lightDirInv, 0);
272
+ const projectedVerts = boundsVertices.map(v => lightPlane.projectPoint(v, new THREE.Vector3()));
273
+ const centralVert = projectedVerts.reduce((a, b) => a.add(b), v.set(0, 0, 0)).divideScalar(projectedVerts.length);
274
+ const radius = projectedVerts.map(v => v.distanceTo(centralVert)).reduce((a, b) => Math.max(a, b));
275
+ const dirLength = boundsVertices.map(x => x.dot(lightDir)).reduce((a, b) => Math.max(a, b)); // Shadows
246
276
 
247
- (_helper$current = helper.current) == null ? void 0 : _helper$current.update();
248
- (_boxHelper$current = boxHelper.current) == null ? void 0 : _boxHelper$current.update();
249
- } // Inject uniforms
277
+ camera.current.position.copy(lightDir.clone().multiplyScalar(dirLength).add(focusPos));
278
+ camera.current.lookAt(scene.current.localToWorld(focusPos.clone()));
279
+ const dirMatrix = lpM.lookAt(camera.current.position, focusPos, v.set(0, 1, 0));
280
+ camera.current.left = -radius;
281
+ camera.current.right = radius;
282
+ camera.current.top = radius;
283
+ camera.current.bottom = -radius;
284
+ const yOffset = v.set(0, radius, 0).applyMatrix4(dirMatrix);
285
+ const yTime = (camera.current.position.y + yOffset.y) / lightDir.y;
286
+ camera.current.near = 0.1;
287
+ camera.current.far = yTime;
288
+ camera.current.updateProjectionMatrix();
289
+ camera.current.updateMatrixWorld(); // Now find size of ground plane
250
290
 
291
+ const groundProjectedCoords = worldVerts.map(v => v.add(lightDir.clone().multiplyScalar(-v.y / lightDir.y)));
292
+ const centerPos = groundProjectedCoords.reduce((a, b) => a.add(b), v.set(0, 0, 0)).divideScalar(groundProjectedCoords.length);
293
+ const maxSize = 2 * groundProjectedCoords.map(v => Math.hypot(v.x - centerPos.x, v.z - centerPos.z)).reduce((a, b) => Math.max(a, b));
294
+ plane.current.scale.setScalar(maxSize);
295
+ plane.current.position.copy(centerPos);
296
+ if (debug) (_helper$current = helper.current) == null ? void 0 : _helper$current.update(); // Inject uniforms
251
297
 
252
- normalMatB.viewMatrix.value = normalMat.viewMatrix.value = camera.current.matrixWorldInverse;
253
- causticsMaterial.cameraMatrixWorld = camera.current.matrixWorld;
254
- causticsMaterial.cameraProjectionMatrixInv = camera.current.projectionMatrixInverse;
255
- causticsMaterial.lightDir = camera.current.getWorldPosition(pos).normalize().multiplyScalar(-1);
256
- causticsMaterial.near = camera.current.near;
257
- causticsMaterial.far = camera.current.far;
258
- causticsMaterial.resolution = resolution;
259
- causticsMaterial.size = frustum;
260
- causticsMaterial.intensity = intensity;
261
- causticsMaterial.worldRadius = worldRadius; // Switch the scene on
298
+ const dirLightNearPlane = lpF.setFromProjectionMatrix(lpM.multiplyMatrices(camera.current.projectionMatrix, camera.current.matrixWorldInverse)).planes[4];
299
+ normalMatB.viewMatrix.value = normalMat.viewMatrix.value = camera.current.matrixWorldInverse;
300
+ causticsMaterial.cameraMatrixWorld = camera.current.matrixWorld;
301
+ causticsMaterial.cameraProjectionMatrixInv = camera.current.projectionMatrixInverse;
302
+ causticsMaterial.lightDir = lightDirInv;
303
+ causticsMaterial.lightPlaneNormal = dirLightNearPlane.normal;
304
+ causticsMaterial.lightPlaneConstant = dirLightNearPlane.constant; //console.log(causticsMaterial.lightDir)
262
305
 
263
- scene.current.visible = true; // Render front face normals
306
+ causticsMaterial.near = camera.current.near;
307
+ causticsMaterial.far = camera.current.far;
308
+ causticsMaterial.resolution = resolution;
309
+ causticsMaterial.size = radius;
310
+ causticsMaterial.intensity = intensity;
311
+ causticsMaterial.worldRadius = worldRadius; // Switch the scene on
264
312
 
265
- gl.setRenderTarget(normalTarget);
266
- gl.clear();
267
- scene.current.overrideMaterial = normalMat;
268
- gl.render(scene.current, camera.current); // Render back face normals, if enabled
313
+ scene.current.visible = true; // Render front face normals
269
314
 
270
- gl.setRenderTarget(normalTargetB);
271
- gl.clear();
315
+ gl.setRenderTarget(normalTarget);
316
+ gl.clear();
317
+ scene.current.overrideMaterial = normalMat;
318
+ gl.render(scene.current, camera.current); // Render back face normals, if enabled
272
319
 
273
- if (backfaces) {
274
- scene.current.overrideMaterial = normalMatB;
275
- gl.render(scene.current, camera.current);
276
- } // Remove the override material
320
+ gl.setRenderTarget(normalTargetB);
321
+ gl.clear();
277
322
 
323
+ if (backfaces) {
324
+ scene.current.overrideMaterial = normalMatB;
325
+ gl.render(scene.current, camera.current);
326
+ } // Remove the override material
278
327
 
279
- scene.current.overrideMaterial = null; // Render front face caustics
280
328
 
281
- causticsMaterial.ior = ior;
282
- plane.current.material.lightProjMatrix = camera.current.projectionMatrix;
283
- plane.current.material.lightViewMatrix = camera.current.matrixWorldInverse;
284
- causticsMaterial.normalTexture = normalTarget.texture;
285
- causticsMaterial.depthTexture = normalTarget.depthTexture;
286
- gl.setRenderTarget(causticsTarget);
287
- gl.clear();
288
- causticsQuad.render(gl); // Render back face caustics, if enabled
329
+ scene.current.overrideMaterial = null; // Render front face caustics
289
330
 
290
- causticsMaterial.ior = backfaceIor;
291
- causticsMaterial.normalTexture = normalTargetB.texture;
292
- causticsMaterial.depthTexture = normalTargetB.depthTexture;
293
- gl.setRenderTarget(causticsTargetB);
294
- gl.clear();
295
- if (backfaces) causticsQuad.render(gl); // Reset render target
331
+ causticsMaterial.ior = ior;
332
+ plane.current.material.lightProjMatrix = camera.current.projectionMatrix;
333
+ plane.current.material.lightViewMatrix = camera.current.matrixWorldInverse;
334
+ causticsMaterial.normalTexture = normalTarget.texture;
335
+ causticsMaterial.depthTexture = normalTarget.depthTexture;
336
+ gl.setRenderTarget(causticsTarget);
337
+ gl.clear();
338
+ causticsQuad.render(gl); // Render back face caustics, if enabled
296
339
 
297
- gl.setRenderTarget(null); // Switch the scene off if caustics is all that's wanted
340
+ causticsMaterial.ior = backfaceIor;
341
+ causticsMaterial.normalTexture = normalTargetB.texture;
342
+ causticsMaterial.depthTexture = normalTargetB.depthTexture;
343
+ gl.setRenderTarget(causticsTargetB);
344
+ gl.clear();
345
+ if (backfaces) causticsQuad.render(gl); // Reset render target
298
346
 
299
- if (causticsOnly) scene.current.visible = false;
347
+ gl.setRenderTarget(null); // Switch the scene off if caustics is all that's wanted
348
+
349
+ if (causticsOnly) scene.current.visible = false;
350
+ }
300
351
  });
301
352
  return /*#__PURE__*/React.createElement("group", _extends({
302
353
  ref: ref
303
354
  }, props), /*#__PURE__*/React.createElement("orthographicCamera", {
304
355
  ref: camera,
305
- up: [0, 1, 0],
306
- left: -frustum,
307
- right: frustum,
308
- top: frustum,
309
- bottom: -frustum,
310
- near: near,
311
- far: far
356
+ up: [0, 1, 0]
312
357
  }), /*#__PURE__*/React.createElement("scene", {
313
358
  ref: scene
314
359
  }, children), /*#__PURE__*/React.createElement("mesh", {
315
360
  ref: plane,
316
- "rotation-x": -Math.PI / 2,
317
- scale: frustum * 2
361
+ "rotation-x": -Math.PI / 2
318
362
  }, /*#__PURE__*/React.createElement("planeGeometry", null), /*#__PURE__*/React.createElement("causticsProjectionMaterial", {
319
363
  transparent: true,
320
364
  color: color,
@@ -324,7 +368,10 @@ const Caustics = /*#__PURE__*/React.forwardRef(({
324
368
  blendSrc: THREE.OneFactor,
325
369
  blendDst: THREE.SrcAlphaFactor,
326
370
  depthWrite: false
327
- })));
371
+ }), debug && /*#__PURE__*/React.createElement(Edges, null, /*#__PURE__*/React.createElement("lineBasicMaterial", {
372
+ color: "#ffff00",
373
+ toneMapped: false
374
+ }))));
328
375
  });
329
376
 
330
377
  export { Caustics };
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),t=require("three"),r=require("react");function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function u(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}var o=n(e),i=u(r);const c=i.forwardRef((function({children:e,disableX:r,disableY:n,disableZ:u,left:c,right:a,top:l,bottom:f,front:d,back:s,onCentered:p,precise:b=!0,...m},g){const h=i.useRef(null),x=i.useRef(null),y=i.useRef(null);return i.useLayoutEffect((()=>{x.current.matrixWorld.identity();const e=(new t.Box3).setFromObject(y.current,b),o=new t.Vector3,i=new t.Sphere,m=e.max.x-e.min.x,g=e.max.y-e.min.y,j=e.max.z-e.min.z;e.getCenter(o),e.getBoundingSphere(i);const v=l?g/2:f?-g/2:0,O=c?-m/2:a?m/2:0,w=d?j/2:s?-j/2:0;x.current.position.set(r?0:-o.x+O,n?0:-o.y+v,u?0:-o.z+w),void 0!==p&&p({parent:h.current.parent,container:h.current,width:m,height:g,depth:j,boundingBox:e,boundingSphere:i,center:o,verticalAlignment:v,horizontalAlignment:O,depthAlignment:w})}),[e]),i.useImperativeHandle(g,(()=>h.current),[]),i.createElement("group",o.default({ref:h},m),i.createElement("group",{ref:x},i.createElement("group",{ref:y},e)))}));exports.Center=c;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),t=require("three"),r=require("react");function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function u(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}var i=n(e),o=u(r);const c=o.forwardRef((function({children:e,disable:r,disableX:n,disableY:u,disableZ:c,left:a,right:l,top:f,bottom:d,front:s,back:p,onCentered:b,precise:m=!0,...g},h){const x=o.useRef(null),y=o.useRef(null),j=o.useRef(null);return o.useLayoutEffect((()=>{y.current.matrixWorld.identity();const e=(new t.Box3).setFromObject(j.current,m),i=new t.Vector3,o=new t.Sphere,g=e.max.x-e.min.x,h=e.max.y-e.min.y,v=e.max.z-e.min.z;e.getCenter(i),e.getBoundingSphere(o);const O=f?h/2:d?-h/2:0,w=a?-g/2:l?g/2:0,z=s?v/2:p?-v/2:0;y.current.position.set(r||n?0:-i.x+w,r||u?0:-i.y+O,r||c?0:-i.z+z),void 0!==b&&b({parent:x.current.parent,container:x.current,width:g,height:h,depth:v,boundingBox:e,boundingSphere:o,center:i,verticalAlignment:O,horizontalAlignment:w,depthAlignment:z})}),[e]),o.useImperativeHandle(h,(()=>x.current),[]),o.createElement("group",i.default({ref:x},g),o.createElement("group",{ref:y},o.createElement("group",{ref:j},e)))}));exports.Center=c;
package/core/Center.d.ts CHANGED
@@ -20,6 +20,7 @@ export declare type CenterProps = {
20
20
  left?: boolean;
21
21
  front?: boolean;
22
22
  back?: boolean;
23
+ disable?: boolean;
23
24
  disableX?: boolean;
24
25
  disableY?: boolean;
25
26
  disableZ?: boolean;
package/core/Center.js CHANGED
@@ -4,6 +4,7 @@ import * as React from 'react';
4
4
 
5
5
  const Center = /*#__PURE__*/React.forwardRef(function Center({
6
6
  children,
7
+ disable,
7
8
  disableX,
8
9
  disableY,
9
10
  disableZ,
@@ -33,7 +34,7 @@ const Center = /*#__PURE__*/React.forwardRef(function Center({
33
34
  const vAlign = top ? height / 2 : bottom ? -height / 2 : 0;
34
35
  const hAlign = left ? -width / 2 : right ? width / 2 : 0;
35
36
  const dAlign = front ? depth / 2 : back ? -depth / 2 : 0;
36
- outer.current.position.set(disableX ? 0 : -center.x + hAlign, disableY ? 0 : -center.y + vAlign, disableZ ? 0 : -center.z + dAlign);
37
+ outer.current.position.set(disable || disableX ? 0 : -center.x + hAlign, disable || disableY ? 0 : -center.y + vAlign, disable || disableZ ? 0 : -center.z + dAlign);
37
38
 
38
39
  if (typeof onCentered !== 'undefined') {
39
40
  onCentered({
@@ -2,12 +2,17 @@ import { ReactThreeFiber } from '@react-three/fiber';
2
2
  import * as React from 'react';
3
3
  import type { Camera, Event } from 'three';
4
4
  import { OrbitControls as OrbitControlsImpl } from 'three-stdlib';
5
+ export declare type OrbitControlsChangeEvent = Event & {
6
+ target: EventTarget & {
7
+ object: Camera;
8
+ };
9
+ };
5
10
  export declare type OrbitControlsProps = Omit<ReactThreeFiber.Overwrite<ReactThreeFiber.Object3DNode<OrbitControlsImpl, typeof OrbitControlsImpl>, {
6
11
  camera?: Camera;
7
12
  domElement?: HTMLElement;
8
13
  enableDamping?: boolean;
9
14
  makeDefault?: boolean;
10
- onChange?: (e?: Event) => void;
15
+ onChange?: (e?: OrbitControlsChangeEvent) => void;
11
16
  onEnd?: (e?: Event) => void;
12
17
  onStart?: (e?: Event) => void;
13
18
  regress?: boolean;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),r=require("three-mesh-bvh");function t(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach((function(t){if("default"!==t){var u=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,u.get?u:{enumerable:!0,get:function(){return e[t]}})}})),r.default=e,Object.freeze(r)}var u=t(e);exports.useBVH=function(e,t){u.useEffect((()=>{if(e.current){e.current.raycast=r.acceleratedRaycast;const u=e.current.geometry;return u.computeBoundsTree=r.computeBoundsTree,u.disposeBoundsTree=r.disposeBoundsTree,u.computeBoundsTree(t),()=>{u.boundsTree&&u.disposeBoundsTree()}}}),[e,t])};
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),r=require("three-mesh-bvh");function t(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach((function(t){if("default"!==t){var u=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,u.get?u:{enumerable:!0,get:function(){return e[t]}})}})),r.default=e,Object.freeze(r)}var u=t(e);exports.useBVH=function(e,t){t={splitStrategy:"SAH",verbose:!1,setBoundingBox:!0,maxDepth:40,maxLeafTris:10,...t},u.useEffect((()=>{if(e.current){e.current.raycast=r.acceleratedRaycast;const u=e.current.geometry;return u.computeBoundsTree=r.computeBoundsTree,u.disposeBoundsTree=r.disposeBoundsTree,u.computeBoundsTree(t),()=>{u.boundsTree&&u.disposeBoundsTree()}}}),[e,JSON.stringify(t)])};
package/core/useBVH.js CHANGED
@@ -2,6 +2,14 @@ import * as React from 'react';
2
2
  import { acceleratedRaycast, computeBoundsTree, disposeBoundsTree } from 'three-mesh-bvh';
3
3
 
4
4
  function useBVH(mesh, options) {
5
+ options = {
6
+ splitStrategy: 'SAH',
7
+ verbose: false,
8
+ setBoundingBox: true,
9
+ maxDepth: 40,
10
+ maxLeafTris: 10,
11
+ ...options
12
+ };
5
13
  React.useEffect(() => {
6
14
  if (mesh.current) {
7
15
  mesh.current.raycast = acceleratedRaycast;
@@ -15,7 +23,7 @@ function useBVH(mesh, options) {
15
23
  }
16
24
  };
17
25
  }
18
- }, [mesh, options]);
26
+ }, [mesh, JSON.stringify(options)]);
19
27
  }
20
28
 
21
29
  export { useBVH };