threlte / threlte Goto Github PK
View Code? Open in Web Editor NEW3D framework for Svelte
Home Page: https://threlte.xyz
License: MIT License
3D framework for Svelte
Home Page: https://threlte.xyz
License: MIT License
Hi,
I found when trying to build my threlte based app for static deployment that I got an error similar to the following: Error [ERR_MODULE_NOT_FOUND]: Cannot find module '<...>/node_modules/three/examples/jsm/postprocessing/EffectComposer' imported from <...>/.svelte-kit/output/server/entries/pages/index.svelte.js Did you mean to import three/examples/jsm/postprocessing/EffectComposer.js?
I saw that in threlte's svelte.config.js there are some extra vite options for threejs. It seems that adding the following "fixes" the issue:
ssr: {
noExternal: ['three']
}
However then index.svelte.js
balloons to 1105.56KiB from 63.85KiB. This is not a big deal IMO. However are there any plans/ideas to fix this?
Adding useThrelte
to the list of imports works fine but as soon as you try to use it like the docs say, the app crashes and you get this error:
Cannot destructure property 'size' of 'vite_ssr_import_3.useThrelte(...)' as it is undefined.
Reproduction Environment
https://stackblitz.com/edit/sveltejs-kit-template-default-1fxljc?file=src/routes/index.svelte
I understand useThrelte
uses a getContext/setContext under the hood but I don't fully grasp that aspect of Svelte so unfortunately I can't fix this myself.
Is this on purpose? Or do you just not care (I mean I don't care either I just noticed it)
I assume this slow down comes from the fact it's doing raytracing every frame, but for on:click
it would be great if this raytracing was actually only done on mouse press, rather the whole time.
Hi, I believe it's a common use case is to set the draco decoder path to https://www.gstatic.com/draco/v1/decoders/
, Should threlte add it as default value?
specifically in this line:
This is a slightly improvement to help devs not to include that URL in every GLTF component in every project.
I was evaluating threlte due to its more complete documentation vs SvelteCubed and I can't really figure out how I can set the background color of the scene. SvelteCubed exposes this as a prop on canvas, but then is setting the background of the scene with that prop. I can't seem to find how/where I can set props (like background color) on the scene in threlte. So maybe this can be made more clear in the docs?
I just ran my vite build and the file size of the useTexture function really stood out:
vite v2.9.14 building for production...
✓ 104 modules transformed.
dist/client.17d98c6c.js 0.42 KiB / gzip: 0.32 KiB
dist/assets/e3b0c442.9e659790.css 0.04 KiB / gzip: 0.05 KiB
dist/Wrapper.214e8078.js 2.12 KiB / gzip: 1.02 KiB
dist/Wrapper.991589b8.js 1.97 KiB / gzip: 0.93 KiB
dist/client.c29c847b.js 50.32 KiB / gzip: 20.35 KiB
dist/chunks/useTexture.37f8dbe3.js 507.74 KiB / gzip: 133.75 KiB
Does this have something to do with the texture/image file included in this file or something? Or might it have something to do with my setup? I'm running in Astro.
PS: is it okay to use .webp as input for useTexture?
Thanks! :)
Right now the frameloop calls ctx.renderer.render(ctx.scene, camera)
and there's no way to intercept or hook onto that.
I guess a property in the renderContext would be great. Something like
const { useRender } = useThrelteRender()
// first argument is the con
useRender(({ renderer, camera, scene }) => {
renderer.render(get(camera), scene)
})
react-three-fiber
solves this with positive and negative indices on the respective property order
of the useFrame
hook. I'm not a huge fan of that as it's somewhat misleading and I like to think in "0 and up" to prioritize and convert that to "up to 0" is a bit of a stretch on the fly. Also computationally a bit more expensive. Also, and I think this is the huge difference: Compared to useFrame
, this hook would only be called in the event of an invalidated frame.
I'm still undecided and I think the whole useFrame
and invalidate
pattern needs a bit of an overhaul.
Hi, any plan to add PointerLockControls in threlte?
error loading dynamically imported module
Hi, as we discussed earlier on discord, it would be awesome to have some recipes for frequently asked questions like #71
Is it suitable to put them in a separate section in the sidebar ?
I'm working on getting a basic WebXR example working with threlte, but I'm having an issue importing the default VRButton from three.js. One of the functions in VRButton is supposed to check that navigator.xr
exists, but trying to access navigator is returning undefined for some reason.
In a new sveltekit project, initialized with npm init svelte@latest
, I'm unable to either preview the site or run the production build. The runtime throws an error stating that the RenderPass
file doesn't exist, though I confirmed that it does exist. Running the site in the dev environment works as expected, though.
I'm using [email protected]
and [email protected]
on macOS 12.1.
Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/Users/christian/www/svtest/node_modules/three/examples/jsm/postprocessing/RenderPass' imported from /Users/christian/www/svtest/.svelte-kit/output/server/entries/pages/index.svelte.js
Did you mean to import [email protected]/node_modules/three/examples/jsm/postprocessing/RenderPass.js?
at new NodeError (node:internal/errors:371:5)
at finalizeResolution (node:internal/modules/esm/resolve:416:11)
at moduleResolve (node:internal/modules/esm/resolve:932:10)
at defaultResolve (node:internal/modules/esm/resolve:1044:11)
at ESMLoader.resolve (node:internal/modules/esm/loader:422:30)
at ESMLoader.getModuleJob (node:internal/modules/esm/loader:222:40)
at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:76:40)
at link (node:internal/modules/esm/module_job:75:36)
Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/Users/christian/www/svtest/node_modules/three/examples/jsm/postprocessing/RenderPass' imported from /Users/christian/www/svtest/.svelte-kit/output/server/entries/pages/index.svelte.js
Did you mean to import [email protected]/node_modules/three/examples/jsm/postprocessing/RenderPass.js?
Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/Users/christian/www/svtest/node_modules/three/examples/jsm/postprocessing/RenderPass' imported from /Users/christian/www/svtest/.svelte-kit/output/server/entries/pages/index.svelte.js
Did you mean to import [email protected]/node_modules/three/examples/jsm/postprocessing/RenderPass.js?
Currently, It's not possible to listen to camera changes or pointer position changes.
The proposed changes would change the ThrelteContext
to this:
type ThrelteContext = {
size: Writable<{ width: number; height: number }>
pointer?: Writable<Vector2>
clock: Clock
camera?: Writable<Camera>
scene: Scene
renderer?: WebGLRenderer
composer?: EffectComposer
invalidate: (reason?: string) => void
}
So it's not the whole context that's a store but rather single properties. This makes it possible to destructure the result of useThrelte
like const { invalidate } = useThrelte()
.
But listening to camera changes would make HUD visibility and general UI work easier and more performant.
First of all, really well made plugin and docs!
I am experiencing issues with the useFrame hook. Error:
[HMR][Svelte] Unrecoverable HMR error in <Three>: next update will trigger a full reload
I got this when trying to make my mesh rotate. Howver, I found that a function like this gives the same error:
useFrame(() => {
console.log('frame')
})
In case it's useful, here's my complete component:
<script>
import { SphereGeometry, MeshStandardMaterial } from 'three'
import {
AmbientLight,
Canvas,
Mesh,
PerspectiveCamera,
PointLight,
useTexture,
useFrame,
} from 'threlte'
const geometry = new SphereGeometry(1, 32, 32)
let rotation = {
x: 0,
y: 0,
z: 0,
}
const textures = useTexture({
map: '/assets/img/maps/colorMap.jpg',
normalMap: '/assets/img/maps/NormalMap.jpg',
roughnessMap: '/assets/img/maps/RougnessMap.jpg',
displacementMap: '/assets/img/maps/DisplacementMap.jpg',
})
const material = new MeshStandardMaterial({ ...textures })
material.displacementScale = 0.02
useFrame(() => {
console.log('frame')
})
</script>
<div class="w-1/2 aspect-1">
<Canvas>
<PerspectiveCamera position={{ x: 0, y: 0, z: 2.4 }}>
<!-- <OrbitControls autoRotate /> -->
</PerspectiveCamera>
<PointLight position={{ x: 50, y: 40, z: 50 }} intensity={0.5} />
<AmbientLight color={0x0d1321} />
<Mesh {geometry} {material} {rotation} />
</Canvas>
</div>
If a <RigidBody>
component is mounted as a child to another object that has been transformed, its transform is in the local space of itself, whereas it should be in world space.
Beginning with Version R139 of three.js it includes a maybe better but definitely different color management by opt-in: https://threejs.org/docs/#manual/en/introduction/Color-management
This might make threltes color management obsolete but it definitely needs a thorough look.
I am trying to build the project with SvelteKit for deployment. Using npm run dev
everything works, but when I try and build, I get:
> Using @sveltejs/adapter-cloudflare
Error [ERR_MODULE_NOT_FOUND]: Cannot find module '[PATH]/node_modules/three/examples/jsm/postprocessing/EffectComposer' imported from [PATH]/.svelte-kit/output/server/entries/pages/index.svelte.js
at finalizeResolution (internal/modules/esm/resolve.js:276:11)
at moduleResolve (internal/modules/esm/resolve.js:699:10)
at Loader.defaultResolve [as _resolve] (internal/modules/esm/resolve.js:810:11)
at Loader.resolve (internal/modules/esm/loader.js:86:40)
at Loader.getModuleJob (internal/modules/esm/loader.js:230:28)
at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:56:40)
at link (internal/modules/esm/module_job.js:55:36)
> 500 /
at file:///[PATH]/node_modules/@sveltejs/kit/dist/chunks/index5.js:409:11
at visit (file:///PATH]/node_modules/@sveltejs/kit/dist/chunks/index5.js:583:5)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
npm ERR! code 1
npm ERR! path [PATH]
npm ERR! command failed
npm ERR! command sh -c svelte-kit build
npm ERR! A complete log of this run can be found in:
npm ERR! [USERPATH]npm/_logs/2022-02-18T04_48_45_935Z-debug.log
It does seem like this is a known issue from googling around, but the solution to lots of those was to move stuff from devDependencies
to regular dependencies
, but that hasn't worked. Any idea what's causing this?
The <Pass>
component is quite handy in its ease of use. However, its implementation seems to depend on the post-processing examples in three.js, so if you want to use something like the postprocessing package it seems you're out of luck. Any thoughts on adding support for this?
In the case of the postprocessing package, the basic API is not quite drop-in but still pretty similar (there's an EffectComposer and a default RenderPass with the same constructor signatures as the three.js examples), so it probably wouldn't be too hard to specifically support this package as an alternative. In theory I suppose there could be other solutions with varied APIs, so one could argue for a more generic way to hook into the render cycle, but in practice I don't know of any other postprocessing solutions, so going that far might be overengineering.
Hi, just updated svelte and found this error:
index.mjs:1857 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading '$$')
at init (index.mjs:1857:50)
at new Canvas (Canvas.svelte? [sm]:53:55)
at createProxiedComponent (svelte-hooks.js:266:9)
at new ProxyComponent (proxy.js:239:20)
at new Proxy<Canvas> (proxy.js:346:11)
at create_fragment (index.svelte? [sm]:32:40)
at init (index.mjs:1877:37)
at new Routes (index.svelte? [sm]:41:55)
at createProxiedComponent (svelte-hooks.js:266:9)
at new ProxyComponent (proxy.js:239:20)
My package.json
"devDependencies": {
"@sveltejs/adapter-auto": "next",
"@sveltejs/kit": "next",
"@types/three": "^0.137.0",
"svelte": "^3.46.4",
"svelte-check": "^2.4.5",
"svelte-preprocess": "^4.10.4",
"tslib": "^2.3.1",
"typescript": "^4.5.5",
}
I'm using the texture loader to load a map on a sphrere. Using this plugin it looks completely different than when I make the same thing on https://threejs.org/editor/ . It's just way lighter than the original image I use for my map.
My component:
<script>
import { MeshStandardMaterial, SphereGeometry } from 'three'
import {
PointLight,
Canvas,
Mesh,
PerspectiveCamera,
useTexture,
} from 'threlte'
const texture = useTexture('/assets/img/maps/ColorMap.jpg')
const material = new MeshStandardMaterial({ map: texture })
</script>
<div>
<Canvas>
<PerspectiveCamera position={{ x: 0, y: 0, z: 3 }} />
<PointLight intensity={0.9} position={{ x: 3, y: 10, z: 10 }} />
<Mesh geometry={new SphereGeometry(1, 64, 64)} {material} />
</Canvas>
</div>
Would really appreciate the help :)
Hello,
I read https://github.com/grischaerbe/threlte/discussions/39 but I didn't get how to get OrbitContols to work with useThrelte if camera is a submodule using CameraInstance or else.
So sticking with default objects I tried:
import {..., PerspectiveCamera} from 'threlte';
let camera = PerspectiveCamera;
...
<camera position={{ x: 1, y: 1, z: 1 }}
<OrbitControls.../>
</camera>
<Mesh lookAt={camera}>
I don't get why the error: Type 'typeof PerspectiveCamera' is not assignable to type 'LookAt'.js(2322)
Would you please help me to get a lookAt and OrbitControls working with a camera?
Hi, I'm trying to create a scene similar to this three.js example: https://github.com/mrdoob/three.js/blob/master/examples/webgl_instancing_dynamic.html
Given an array (particles) I use useFrame to change the position, rotation, and scale of each item in the array, and then I use that particle array like the following code:
<InstancedMesh {geometry} {material}>
{#each particles as particle, index}
<Instance id={String(index)} position={particle.position}
rotation={particle.rotation}
scale={particle.scale} />
{/each}
</InstancedMesh>
However I get the error:
Uncaught (in promise) TypeError: Cannot destructure property 'registerInstance' of 'useInstancedMesh(...)' as it is undefined.
at instance_1 (Instance.svelte? [sm]:13:9)
at init (index.mjs:1876:11)
at new Instance (Instance.svelte? [sm]:29:18)
at createProxiedComponent (svelte-hooks.js:341:9)
at new ProxyComponent (proxy.js:242:7)
at new Proxy (proxy.js:349:11)
at create_each_block (Swarm.svelte:5:50)
at Array.create_default_slot (Swarm.svelte:67:9)
at create_slot (index.mjs:69:27)
at Array.create_default_slot (InstancedMesh.svelte? [sm]:179:28)
I don't understand what I'm doing wrong, someone please can help ?
Thanks
Just started trying out Threlte and like it a lot :)
I wonder what the reason is for making the scene auto-render if there is an interactive object in the scene? I tested to remove lines 47-48 in frameloop.js and using the orbit-control and clicking on objects works just fine. I have not tested hover states etc yet, though.
I really like that the default in threlte is to not render if nothing has changed in the scene, so if auto-update is needed for some but not all interactivity it would be great to be able to have a setting for this.
Cheers,
David
In three.js normally, it is possible to use selective passes (e.g. here and here) by rendering multiple layers.
Using the inbuilt postprocessing in Threlte is something similar possible natively (applying passes to specific layers ideally, but objects otherwise), or should I aim to recreate this effect the way it is done in examples?
Adding a glitch pass to the basic scene in your guide doesn't seem to work, possibly as a result of this line being deleted in ea2f5bf:
ctx.composer.addPass(new RenderPass(ctx.scene, ctx.camera ?? new Camera()))
The pass works when I reintroduce the line on lib/renderer right after ctx.composer = new EffectComposer(ctx.renderer);
If points length = 0, it appears that we get a console error.
https://svelte.dev/repl/4eef6c2a692149cdaf4061c3dbfe61ba?version=3.46.2
Hey :) As we discussed! Some of this is superficial, just wanted to have somewhere to put everything I thought along the way. (Note I'm commenting without using it yet).
default
keyword here? I don't know anything about svelte modules export { default as OrthographicCamera } from './cameras/OrthographicCamera.svelte'
export OrthographicCamera from 'OrthographicCamera'
scene?.traverse...
if(!objIsMesh()) return
Mesh
. Wouldn't these normally be the same?thing[something] = (thing[something] ?? 0) + 1
debugFrameloopMessage
sounds like a type. There's no context on the Frameloop in this scope. Probably better to name it debugMessage
lib/controls
. These seem like the project could be broken into something like core / convenience. Kind of like drei/r3f. You can use a tool like madge
to see your dependency graph to make the split. May help keep cognitive effort down in working in the codebase.Threlte is a component library for svelte to build and render three.js scenes declaratively and state-driven in Svelte apps.
Do you batch the invalidations? This could be a good thing to mention because it allows you to debug frame budgets pretty easily.It's inspired by the sensible defaults of [react-three-fiber](https://github.com/pmndrs/react-three-fiber), the simplicity and effectiveness of Sveltes reactivity model and [Svelte Cubed](https://github.com/Rich-Harris/svelte-cubed).
Maybe here it's good to mention what you do differently / the design goal of the lib.It also aims to provide the building blocks to quickly extend threlte when it's needed.
Probably need more context on this. Maybe a snippet or something.Build your first scene:
You can unprettyfy the imports in the code snippet etc by inlining them. This will keep the focus on the parts that need focus.It should look something like this:
Can cut the whitespace out of the image, compress properly and use a short gif maybe?position: Position | undefined = undefined
could be a little prettier.I haven't yet had a go at playing with it :) Will have to wait for next weekend. Got some dark souls to fail at.
Hello! I've been using Svelte for a long time, but am very much still learning Three.js. I saw Svelte Cubed and tried out the demo and started working on an idea I had, and then discovered both threlte and svelthree.
My question (which also goes to @vatro and @Rich-Harris) is how I should pick which one of these libraries to use? What are the philosophical differences in how they structured or what are the fundamental differences and what about them might matter to developers wanting to use them?
This question isn't meant to be discouraging at all, I absolutely applaud all the work that is going here, they all look really amazing! However it feels like Svelte itself is a relatively small community and so then to have three competing Three.js Svelte libraries leaves me confused as to which one to pick and also maybe feels like precious energy is being used to compete when perhaps thrashing out the differences and then cooperating might also be a great way forward?
Currently, the sidebar is quite long, I think a tad too long. KitDocs does not provide the means to have a collapsible sidebar, so there's some effort involved.
Hi there,
What a wonderful project!
I have a hard time seeing anything but white background color though.
Following the readme, I made a REPL, https://svelte.dev/repl/23b35cb4fb6b43d8b1df3848f6fef93d?version=3.46.4
But I don't see any sky or ground :)
Any idea?
Bonus question: Do you have shaders too?
Have a great day!
I've noticed that we're copying the same(?) tweakpane code between examples. Should we just put it in one place and import?
Maybe we could use a @threlte/utils package where non-three related code lives. Like this tweapkane thing, but also Keyboard controller proposed by @AlexWarnes on discord?
A component to bridge the context to be able to use it outside the <Canvas>
element.
hi, thanks for the brilliant work, tell pls if there are plans to add a similar GLTF, also an OBJ models?
Hi!
I would like to add an AxesHelper
to the Canvas
.
What would be the best way to do it?
Thanks a lot
HTML is rendered no matter whether the parent is visible or not.
I made a demo that demonstrates this
And here's a quick example:
<script>
import {Group} from '@threlte/core';
import {HTML} from '@threlte/extras';
</script>
<Group visible={false}>
<HTML transform>
<h1>Hello world</h1>
</HTML>
</Group>
Threlte will render Hello world
The Docs are built with KitDocs, so we'd need to check their support first.
Since threejs typically takes some time to load, it is good practice to add a loading overlay on pages where the object in included in the first section.
In ThreeJS we can listen with LoadingManager to the completion of the load. However, I can't get it to work using threlte. I tried putting the first piece of code from the Threejs website (https://threejs.org/docs/index.html#api/en/loaders/managers/LoadingManager) in component aswell as in my wrapper. However, nothing is heppening.
What would be the recommend way to doing this?
While Mesh
has been implemented fine, Points
has not been put in. It can be bodged in very easily, but duplicating the Mesh.svelte
, replacing
setup(new THREE.Mesh(geometry, material));
with
setup(new THREE.Points(geometry, material));
and fiddling around with exports, but there may well be a more efficient way of doing things.
I've tried to use useFrame()
but I get the issue
Function called outside component initialization
I see that the docs say to use it with Canvas, but I'm not entirely sure how. The examples given use it the same way I do.
I need to load in 7 fairly large textures using
threlte.useTexture(imgPath);
where imgPath
is calculated from Vite's import
overloading for images, and exported in a component. Is there a better way of importing/loading the images that allows them to be cached, so it doesn't take 2-3 seconds to load them all in every time?
As far as i can tell the frustrum is always linked to the size of the parent container/canvas, which probably is good enough in most cases. I would like to have more control over the frustrum like in vanilla three.js (left,right,top,bottom).
So could imagine having some sort of switch deciding the size based on the parent container (like now) or a custom frustrum.
I´m not sure which way is better as in extending the $size store in some way
https://github.com/grischaerbe/threlte/blob/087f26706481188bc159abaffa86f0f76beeabef/src/lib/Canvas.svelte#L76-L77
or adding new reactive props (left,right,top,bottom) just for the OrthographicCamera
https://github.com/grischaerbe/threlte/blob/087f26706481188bc159abaffa86f0f76beeabef/src/lib/cameras/OrthographicCamera.svelte#L22-L26
Some guidance which way would fit best would be appreciated :).
Hello @grischaerbe , thanks for your amazing work.
I updated threlte to 3.6.1
and some animated GLTFs don't support interactivity!
I have two different model components here and here, and a static model component here
The demo is here
The cursor should be pointer when hovering over any model, but it doesn't! work for the animated ones!
It would be great to have support for RTL text like Arabic.
I made a demo where Arabic text doesn't render.
Please note that drei supports RTL text
I am plotting around 2K to 5K lines dynamically. However, when the number of point varies I get this error in the console which makes the line disappear.
I believe this is due to not being able to preallocate a large enough buffer for points. Would be nice if this is handled behind the scenes.
[.WebGL-0x10004cab800] GL_INVALID_OPERATION: Vertex buffer is not big enough for the draw call
When dragging the scene and ending the drag above an interactive object, a click event is triggered from the object. When dragging on touch screen I don't get this behavior, and I would expect to only get the click handler if I have not initiated a drag.
In previous projects with three I have listened on movement from the orbit-control and stopped the propagation of the click events if the user has moved more than threshold values for distance or duration. I've also done the opposite, if a scene object is dragged the orbit-control is inactivated during the drag duration. Not sure how the interactivity works in threlte yet, though.
Cheers,
David
I have a project where i use WebGLRenderTarget´s as Textures for material kind of like this.
Is there a way to hook into the rendercall to render all renderTargets before the final image + control of the framebuffer?
I saw the that its possible to maybe use the EffectComposer for a similar result, but i never used that before so i will give this a try first. Maybe the Topic is also related to #29
br :)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.