Rendering Three in a react environment #536
SunbeamRapier
started this conversation in
General
Replies: 6 comments 3 replies
-
i am not sure i understand the question. r3f renders for you, you just render meshes, materials and so on. |
Beta Was this translation helpful? Give feedback.
0 replies
-
Hi mate
I was assuming that the react render would handle all the react stuff and the three renderer would handle the animation…
I have been attempting to convert your code to run in App.js in such a way that I can animate three objects in individual containers.
I am having a few issues here - hopefully you can point me in the right direction…
APP.ls code
// I have embedded the threeJS script stuff within container1but I am not sure how this is going to work… If the three rendered is going to render the whole app
then I guess that part of the code, at least, will have to be in index.js.
The code files are from [ https://threejs.org/docs/index.html#manual/en/introduction/Creating-a-scene <https://threejs.org/docs/index.html#manual/en/introduction/Creating-a-scene> ] and has been implemented as follows:
Index.js
—————
I haven’t moved the three renderer to index.js to replace the react renderer - I will have three models to render in three containers. So I guess that is three scenes… I have only created the first one as yet...
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as THREE from 'three';
import { Scene } from 'three';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
App.js
————
import React from 'react';
import './App.css';
import * as THREE from 'three';
import reactthreefiber from 'three';
import canvas from 'reactthreefiber';
function App() {
return (
<div className="App">
<header className="App-header">threeJS animated logo test</header>
<body>
<div class="container1">
<div class="canvas">{canvas}</div> {/* canvas { display: block; } produced error on colon
moved display block code to CSS */}
<script src="js/three.js"></script>
<script>
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var geometry = new THREE.BoxGeometry();
var material = new THREE.MeshBasicMaterial); {/*( { color: 0x00ff00 } error on colon */}
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
camera.position.z = 5;
function animate() {
cube.rotation.x += 0.01,
cube.rotation.y += 0.01,
renderer.render(scene, camera)
}
animate();
</script>
</div> {/* end of div container1 */}
<div class="container2">2</div>
<div class="container3">3</div>
</body>
</div>
);
}
export default App;
App.CSS
——————
.App {
text-align: center;
}
.App-header {
background-color: yellow;
min-height: 5vh;
align: left;
justify-content: left;
font-size: calc(10px + 2vmin);
color: grey;
}
.container1 {
width:250px;
margin: 0;
height:300px;
display: inline-block;
background:grey;
}
.canvas {
display: block;
}
.container2 {
width:250px;
margin: 0;
height:300px;
display: inline-block;
background:grey;
}
.container3 {
width:500px;
margin: 0;
height:300px;
display: inline-block;
background:grey;
}
compile-time Issues
Cube is defined in one function and is not accessible in the animate function. I will have to modify the code to create a new function CreateGeometry and call it to obtain the cube in the animate function.
The code at line 26 color: 0x00ff00. produced an error on the colon - I moved it to the CSS
I haven’t fiddled any further with it at this stage. Was t
I am assuming, given the error messages, that the get started code is for JS rather than React…
Any assistance you can provide is appreciated.
Stephen
ps: I didn’t post this on the site as well - I can if you want me to do so…
… On 26 Jun 2020, at 9:14 pm, Paul Henschel ***@***.***> wrote:
i am not sure i understand the question. r3f renders for you, you just render meshes, materials and so on.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub <#536 (comment)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AI3XEBKALKCEOKX5UOKLMWTRYR7KFANCNFSM4OI473LA>.
|
Beta Was this translation helpful? Give feedback.
1 reply
-
Ok. The script stuff is from threeJS website.
Do I want the whole app rendered at 60fps? What happens if the user is typing in an input box and it is re-rendered?
Normally you would only get a full app render if you made a change or there was a state change. Does your renderer render only the changes or everything every time?
That’s why I was thinking both renderers would be working: yours for the animation only and everything else via the usual react render process.
At 60fps is it quite demanding on cpu?
Sorry to ask all these questions but all the examples are just an animation and I’m trying to get my head around how that works in a business website with lots of components and other stuff going on.
I’ll check out the demo in the morning. Nearly midnight in Sydney. Enjoy your day.
Stephen
…Sent from my iPhone
On 29 Jun 2020, at 5:00 pm, Paul Henschel ***@***.***> wrote:
I'm honestly not sure what you're trying to do there. React builds the scene, r3f renders for you 60fps. You don't need webglrenderer. I also don't understand the script tag stuff. Better start from scratch, go to the r3f GitHub, read through the API and fork the basic demo with the two rotating cubes.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
Beta Was this translation helpful? Give feedback.
1 reply
-
Hi mate
Ok, so let’s see if I have this right now…
a) the animation inside the container is rendered by threeJS at 60fps.
b) the threeJS renderer doesn’t handle any other render requirements such as changes to a navbar tile when the colour and font changes on a user click event.
c) when the threeJS renderer rotates the model, the changes are not seen by the react renderer and this does not result in another render of the DOM.
The code below (for the first model only) will run in a React component ‘logo.js’ within the react app:
import ReactDOM from 'react-dom'
import React, { useRef, useState } from 'react'
import { Canvas, useFrame } from 'react-three-fiber'
import './styles.css'
import 'three'
import * as THREE from 'three';
import GLTFLoader from 'three-gltf-loader';
const loader = new GLTFLoader();
const scene = "";
loader.load(
'/public/1_BigW4-W.glb.',
( gltf ) => {
// called when the resource is loaded
scene.add( gltf.scene );
},
( xhr ) => {
// called while loading is progressing
console.log( `${( xhr.loaded / xhr.total * 100 )}% loaded` );
},
( error ) => {
// called when loading has errors
console.error( 'An error happened', error );
},
);
function Box(props) {
// This reference will give us direct access to the mesh
const mesh = useRef()
// Set up state for the hovered and active state
const [hovered, setHover] = useState(false)
const [active, setActive] = useState(false)
// Rotate mesh every frame, this is outside of React without overhead
useFrame(() => (mesh.current.rotation.x = mesh.current.rotation.y += 0.01))
return (
<mesh
{...props}
ref={mesh}
scale={active ? [1.5, 1.5, 1.5] : [1, 1, 1]}
onClick={e => setActive(!active)}
onPointerOver={e => setHover(true)}
onPointerOut={e => setHover(false)}>
<boxBufferGeometry attach="geometry" args={[1, 1, 1]} />
<meshStandardMaterial attach="material" color={hovered ? 'hotpink' : 'orange'} />
</mesh>
)
}
ReactDOM.render(
<Canvas colorManagement>
<ambientLight />
<pointLight position={[10, 10, 10]} />
<Box position={[-1.2, 0, 0]} />
<Box position={[1.2, 0, 0]} />
</Canvas>,
document.getElementById('root')
)
So, the code now runs in Logo.js, including the threeJS renderer.
d) So if I change the render DIV to document.getElementById(‘container1’) then the model will be rendered inside the container in the Logo.JS code component and, at this point, no other rendering will occur.
e) The existing DOM render in Index.JS will continue to render other changes to the DOM. The sequence is:
LogoJS exports to Header.JS
which exports to App.JS
which exports to Index.JS
and is rendered by the react render:
import React from 'react';
import ReactDOM from 'react-dom';
import './components/css/index.css';
import App from './components/App';
import "./components/css/Header.css";
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
f) The demo software with the two boxes runs in Index.JS and only renders the animation - there being no other objects to render. When the animation is running within an app with several components which all require rendering when the user makes changes to anything in the DOM, it seems to me that both renderers are required.
In this application, the animation is for the logo in Logo.JS should sit in a container to the left of the Navbar in the Header.JS. When the user clicks a tile in the Navbar, the colours and font change and this is rendered by the React renderer.
As long as the threeJS rendering does not generate a render of the whole app then there shouldn’t be a major performance hit. "this is outside of React without overhead"
Anyway, unless you advise otherwise, that’s what I will attempt later today.
And, yes, I apologise for the muddle with the threeJS code - I have been down so many React rabbit holes over the last few months I am losing track of what I have tried, where I found things, and what works with what… I ended up on the wrong github page and another rabbit hole…. I probably need a break but I can’t afford the time :-(
Thanks again for your forbearance. Fingers crossed I will get this working now.
Stephen
… On 30 Jun 2020, at 12:03 am, Paul Henschel ***@***.***> wrote:
this isnt how it works. threejs renders on the gpu, it renders just like in your snippet. it has nothing to do with input boxes and react-dom, these two are entirely apart. if you want to render 3d content only on changes, that is possible, too: <Canvas invalidateFrameloop ...>
as for plain threejs, you shouldn't mix. either you use plain threejs, or r3f where you get to do the same thing but declarative, way easier, less boilerplate.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub <#536 (reply in thread)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AI3XEBJE6S6Q7IHHLOYX6D3RZCNKTANCNFSM4OI473LA>.
|
Beta Was this translation helpful? Give feedback.
1 reply
-
Hi mate
Thanks for the codeSandbox. I was able to take that code and transfer it to my vsCode setup, add the dependencies and get it to run properly.
So I have now added the code for Suzanne to my existing app and am nearly there - but poor Suzanne has no face!
This happened the first time I ran it in its own app and I fixed it by installing the missing dependecies, but that hasn’t worked this time.
My file structure is a little different.
Maybe the file references are incorrect for this structure or some of the files are in the wrong place? I have tried moving things around but I am not really sure what the issue is here, or what fiie(s) are failing to load…
I am getting a few errors also - but I get the same errors when I run the code from the sandbox in its own app...
This is the code from your App.js which is running as Logo.js on my system. It’s the identical code except for the name of the Export which is Logo instead of App.
Just in case I don’t have everything installed…
I am hoping you can see at a glance what the problem is here.
Once I have this working I will replace Suzanne with onr of my Blender models and if that works I will change the background and look at the animation :-)
Thanmks again for your assistance here - I am sorry this is taking so long. It is more complex than I imagined at the start!
Stephen
… On 30 Jun 2020, at 9:31 pm, Paul Henschel ***@***.***> wrote:
you dont need that gltfloader stuff. threejs own gltfloader is a module now. use useLoader for convenience: https://codesandbox.io/s/r3f-ibl-envmap-simple-p5zf9 <https://codesandbox.io/s/r3f-ibl-envmap-simple-p5zf9>
rendering between three and react is completely apart, it has nothing to do with one another. three render 60fps, react renders when props change.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub <#536 (reply in thread)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AI3XEBNWDVP75KRNQXIWSZLRZHEHXANCNFSM4OI473LA>.
|
Beta Was this translation helpful? Give feedback.
0 replies
-
Hi mate
The issue was the version of react-three-fiber. It took me a while to figure that out but installing Beta 10 worked…
Stephen
… On 30 Jun 2020, at 9:31 pm, Paul Henschel ***@***.***> wrote:
you dont need that gltfloader stuff. threejs own gltfloader is a module now. use useLoader for convenience: https://codesandbox.io/s/r3f-ibl-envmap-simple-p5zf9 <https://codesandbox.io/s/r3f-ibl-envmap-simple-p5zf9>
rendering between three and react is completely apart, it has nothing to do with one another. three render 60fps, react renders when props change.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub <#536 (reply in thread)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AI3XEBNWDVP75KRNQXIWSZLRZHEHXANCNFSM4OI473LA>.
|
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
I have my code for a container with an animation in a react component. I am assuming that I need to include the three render code in this component which will then be exported to App.js and then to index.js with the other components.
Q1: is the animated component within the container seen by react as a fixed component (unchanging) or will every change to the animation will result in a new export to App/Index and another react render?
Q2: To build this component in the container I am thinking I will need to add all the scene code, and thethree renderer to this container. IS that the correct approach?
Cheers
Rapier
Beta Was this translation helpful? Give feedback.
All reactions