Add pointLight in react three fiber - three.js

I want to add pointlight in react three fiber and it seems that it follows different syntax from usual three.js syntax.

All three.js objects will be treated as native JSX elements. The general rule is that React Three Fiber components are available under the camel-case version. Hence do this to add a point source light like this -
<pointLight position={[0, 10, -5]} intensity={1} color="#fff" />

Related

How to make object from one component 'lookAt' another object in another component?

I'm fairly new to both React and Threejs and am having a hard time wrapping my head around how to make an object from one component lookAt another object from another component using react-three-fiber and #react-three/drei. I have a custom PerspectiveCamera with controls in one component and some Text using #react-three/drei in another component. What I would like to happen is have the Text and planeGeometry face the camera at all times
Any help would be great! CodeSandbox here: https://codesandbox.io/s/wonderful-chaplygin-hihx70?file=/src/App.js

Modelviewer environment of three.js editor in react-three-fiber

I'm working on a little project with react-three-fiber. If I load my .gbl 3D Model into the scene it's completly dark even if I use the ambientlight in the canvas. But in the three.js editor it looks exactly like I want it if I use the Modeviewer environment. Is it possbile to download this environmet somewhere and use it in my project?
yes, the stage component from the drei library https://twitter.com/0xca0a/status/1402975317174726656 all you need is wrap your model into <Stage>. as for models being dark even with ambientlight, this is usually related to wrong materials, for instance metalness=1. take a look here: https://discourse.threejs.org/t/ambient-light-and-gltf-models-not-working-results-in-black-model/7428/5

Suggested architecture to re-render scene only if scene has changed?

I have a complex web application, with several sub-views / widgets that add objects to the main scene.
Most simple THREE.js examples have a continous render loop, that re-renders the scene periodically.
This seems like a waste of ressources to me.
Therfore, I only want to re-render the scene if something has changed.
However, the sub-views / widgets do change things (like position of objects) in the scene on their own.
Is there something like a "scene.hasChanged" flag, that I can use to deceide if the scene needs to be rerendered? Or do I have to implement a parallel flag or notification structure myself?
Or is there another common solution to this?
Based on what you have written so far, it seems you have to implement a custom solution. Certain three.js examples like webgl_loader_gltf do not use an animation loop but utilize change events from the controls. The relevant line of code is
controls.addEventListener( 'change', render );
However, if more factors than just the user interaction trigger renderings, it's necessary to build some sort of notification/event system by yourself.
three.js R113

Normal Map Values with ThreeJS GLTF Blender Exporter

If I set the "Normal" slider value in Blender under "Geometry" for the texture to 2.0. I see a normal value of X: 1, Y: -1 when I look at the object in the console log. Am I missing something?
I'm using ThreeJS R97.
From your description of "Normal slider under Geometry", I'm guessing you're talking about Blender 2.79x or earlier, Blender's built-in renderer, material settings, where that slider controls the strength of the applied normal map.
So, a couple of things to talk about here. First, the glTF exporter doesn't officially support the built-in Blender Render materials, and this slider is not hooked up as you've already discovered. The development effort for the exporter is now focused on an addon called glTF-Blender-IO, which works in Blender 2.79 but actually ships pre-installed in Blender 2.80 Beta.
This addon works with the Cycles and Eevee engines using the "Principled BSDF" node, optionally in combination with a few helper nodes such as "Normal Map". So, the glTF exporter expects to find a normal map hooked up like this:
Keep in mind, the glTF format doesn't contain the nodes themselves, but, the exporter will understand this hookup and will write the normal map into the glTF file, along with optionally the base color, metallic, roughness, and emissive maps (via another separate node needed for emissive).
But there's a small wrinkle in this plan, it looks like strength is not hooked up yet. Blender's "Normal Map" node contains a "strength" parameter, and the glTF format contains a corresponding parameter called normalTexture.scale which does the same thing, but, it looks like the exporter is not copying the value from one place to the other. I filed issue #241 on that, and hopefully that will get fixed eventually.
In ThreeJS, the values of X: 1, Y: -1 are intentional for a unit-strength normal map. ThreeJS normal maps use a different Y-convention from the glTF format, so Y is intentionally flipped when loading a normal map from glTF. So, to double the strength of it, you would set X: 2, Y: -2. For now, it looks like assigning this in code (or manually editing a glTF) are the only options until the exporter has a feature added to copy the missing strength parameter.

Three.js within web worker: Simulating animation without rendering to canvas

I have a hypothetical question:
Is it possible to simulate an animation of objects without rendering it to the canvas. I just want to capture objects' position using Vector.project(camera) and present it using CSS. And THREE.DeviceOrientationControls controls how the camera "view" the simulation.
I tried commenting THREE.WebGLRenderer, but it seems that THREE.PerpectiveCamera cannot update it's MatrixWorld property. Hence, the camera seems to not move and the Vector.project(camera) gives a static value. I do this because I need to put my three.js codes within a web worker.
Do I need still need to use THREE.WebGLRenderer to have a working simulation?
UPDATE:
I checked the following:
I digged deeper into ((three.scene.getObjectByName("one")).matrixWorld.getPosition()).project(three.camera);, I inspect the following values, having the above requirement (inside web worker, no renderer), using this example:
matrix: {"elements":{"0":3.2167603969573975,"1":0,"2":0,"3":0,"4":0,"5":2.1445069313049316,"6":0,"7":0,"8":0,"9":0,"10":-1.000100016593933,"11":-1,"12":5.4684929847717285,"13":2.1445069313049316,"14":-0.2000100016593933,"15":0}}
camera.projectionMatrix: {"elements":{"0":3.2167603969573975,"1":0,"2":0,"3":0,"4":0,"5":2.1445069313049316,"6":0,"7":0,"8":0,"9":0,"10":-1.000100016593933,"11":-1,"12":0,"13":0,"14":-0.2000100016593933,"15":0}}
camera.matrixWorld: {"elements":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":1,"6":0,"7":0,"8":0,"9":0,"10":1,"11":0,"12":-1.7000000476837158,"13":-1,"14":0,"15":1}}
matrix.getInverse(camera.matrixWorld): {"elements":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":1,"6":0,"7":0,"8":0,"9":0,"10":1,"11":0,"12":1.7000000476837158,"13":1,"14":0,"15":1}}
matrix.multiplyMatrices(camera.projectionMatrix, matrix.getInverse(camera.matrixWorld)): {"elements":{"0":3.2167603969573975,"1":0,"2":0,"3":0,"4":0,"5":2.1445069313049316,"6":0,"7":0,"8":0,"9":0,"10":-1.000100016593933,"11":-1,"12":5.4684929847717285,"13":2.1445069313049316,"14":-0.2000100016593933,"15":0}}
But, when normal (no modification), I inspect the following:
matrix: {"elements":{"0":3.2167603969573975,"1":0,"2":0,"3":0,"4":0,"5":2.1445069313049316,"6":0,"7":0,"8":0,"9":0,"10":-1.000100016593933,"11":-1,"12":5.4684929847717285,"13":2.1445069313049316,"14":-0.2000100016593933,"15":0}}
camera.projectionMatrix: {"elements":{"0":3.2167603969573975,"1":0,"2":0,"3":0,"4":0,"5":2.1445069313049316,"6":0,"7":0,"8":0,"9":0,"10":-1.000100016593933,"11":-1,"12":0,"13":0,"14":-0.2000100016593933,"15":0}}
camera.matrixWorld: {"elements":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":-2.220446049250313e-16,"6":-1,"7":0,"8":0,"9":1,"10":-2.220446049250313e-16,"11":0,"12":-1.7000000476837158,"13":-1,"14":0,"15":1}}
matrix.getInverse(camera.matrixWorld): {"elements":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":-2.220446049250313e-16,"6":1,"7":0,"8":0,"9":-1,"10":-2.220446049250313e-16,"11":0,"12":1.7000000476837158,"13":-2.220446049250313e-16,"14":1,"15":1}}
matrix.multiplyMatrices(camera.projectionMatrix, matrix.getInverse(camera.matrixWorld)): {"elements":{"0":3.2167603969573975,"1":0,"2":0,"3":0,"4":0,"5":-4.761761943205948e-16,"6":-1.000100016593933,"7":-1,"8":0,"9":-2.1445069313049316,"10":2.2206681307011713e-16,"11":2.220446049250313e-16,"12":5.4684929847717285,"13":-4.761761943205948e-16,"14":-1.2001099586486816,"15":-1}}
I noticed that the camera.matrixWorld property has significant difference in both condition. I do not understand what makes the difference.
Apparently, the following lines from THREE.WebGLRenderer.render are still needed to update camera.matrixWorld property:
scene.updateMatrixWorld();
camera.updateMatrixWorld();
camera.matrixWorldInverse.getInverse(vs._3.camera.matrixWorld);

Resources