I want to create a (semi) transparent box
<mesh position={position} transparent opacity={0.1}>
<boxGeometry args={scale}>
<meshPhingMaterial color={(0.5, 0.5, 0.5)} opacity={0.1} transparent />
</boxGeometry>
</mesh>
I tried several values for opacity, but the box stays non transparent.
What's wrong?
<mesh position={position} scale={scale}>
<boxGeometry />
<meshPhongMaterial color="#ff0000" opacity={0.1} transparent />
</mesh>
you can consult threejs docs for all of these objects: https://threejs.org/docs/index.html#manual/en/introduction/Creating-a-scene all the props and constructor args are listed in there.
and at least once skip through this section real quick https://docs.pmnd.rs/react-three-fiber/API/objects to learn about react semantics.
ps. (0.5, 0.5, 0.5) in javascript just means that it will return the last number. const a = (1, 2, 3) yields 3.
pps. it is better to scale the mesh instead of constructor args. if you change args the object must get re-created because you literally do new BoxGeometry(scale). on the mesh on the other hand it won't have to do it and it's faster.
Related
I'm trying to add a 3D effect on a plane in a React site. But I haven't been able to create a plane that fills the camera, like in all the Three.js shader or post-processing examples.
I have tried using an Orthographic Camera + plane, based on this answer, like so:
<Canvas>
<OrthographicCamera left={-1} right={1} top={1} bottom={-1} near={0} far={1} />
<planeGeometry args={[2, 2]} />
</OrthographicCamera>
</Canvas>
But this results in a small square in the middle of the canvas.
I also tried using a ScreenQuad, like so:
<Canvas style={{width: '100vw', height: '100vh'}}>
<ScreenQuad />
</Canvas>
But this results in a triangle in the middle of the canvas.
Here is a repo reproducing both examples: https://github.com/Cecile-Lebleu/gatsby-r3f-bug
I can only cover the Canvas by blowing up the size of the plane, but it's not a good solution: the effect looks giant on small screens and still cropped on larger screens.
What's going on? How can I make a simple plane that covers the camera regardless of Canvas size?
In case anyone ever runs into this, the solution thanks to #0xca0a:
Set the camera to default: <OrthographicCamera makeDefault>
And scale the mesh to fit the viewport.
const viewport = useThree(state => state.viewport)
return (
<mesh scale={[viewport.width, viewport.height, 1]}>
<planeGeometry />
</mesh>
Add in useAspect for responsive images:
function Scene() {
const size = useAspect(1800, 1000)
return (
<mesh scale={size}>
)}
The first two args are the width and height of the image, it then calculates a viewport big enough to cover, and it's responsive.
Or just use drei/image.
The problem
When loading my GLTF inside the canvas element of react-three-fiber in a 100vw x 100vh div the GLTF model seems to look fine. However when I change the size of the containing div and canvas to 50vw x 100vh the GLTF model seems to be stretched.
100vw x 100vh screenshot
100vw x 50 vh screenshot
What I have tried so far
I have tried to set the aspect ratio of the camera.
<Controls
enableDamping
rotateSpeed={0.3}
dampingFactor={0.1}
cameraProps={{
position: [11, 11, 11],
near: 0.1,
far: 1000,
fov: 50,
aspect: [random number here doesn't change anything]
}}
maxDistance={18}
/>
I have tried to add a window event listener on resize and setting the aspect ratio like so:
function onWindowResize() {
camera.aspect = 2.0 -> doesn't have any effect, not even with random numbers
camera.updateProjectionMatrix();
renderer.setSize(book.clientWidth, book.clientHeight);
}
Nothing of the above seems to work and I am out of options. I found several related posts on SO en google. I tried them all..
Versions etc
"#react-three/drei": "^7.25.0",
"#react-three/fiber": "^7.0.21",
"#react-three/postprocessing": "^2.0.5",
I am using orbot controls and a perspective camera. Here is the link to the code sandbox.
https://codesandbox.io/s/36uiq?file=/src/index.js
Hopefully someone is able to help me out.
When updating your camera's aspect ratio, make sure it matches your renderer's aspect ratio:
camera.aspect = book.clientWidth / book.clientHeight;
camera.updateProjectionMatrix();
renderer.setSize( book.clientWidth, book.clientHeight );
Make sure that camera exists, and it's the camera you're using to perform your render.
someone knows how to assign a gradient to a MeshBasicMaterials that in my case is a Sphere?
At the moment I have an orange #ff8300 sphere that I would like to have a gradient from #ffff00 to #ff0000.
🙏
<mesh>
<sphereBufferGeometry args={[0.8, 30, 30]} attach="geometry" />
<meshBasicMaterial color={0xff8300} attach="material" />
</mesh>
I found that the easiest way to accomplish a gradient material with #react-three/fiber is using the GradientTexture helper component included with #react-three/drei.
Here's a simple example that's mostly straight from the docs:
<mesh ref={sphereRef}>
<sphereGeometry args={[2.5, 30, 30]} attach="geometry" />
<meshBasicMaterial>
<GradientTexture
stops={[0, 1]} // As many stops as you want
colors={['aquamarine', 'hotpink']} // Colors need to match the number of stops
size={1024} // Size is optional, default = 1024
/>
</meshBasicMaterial>
</mesh>
I am using fly controls with drei. I can't seem to set the lookat position for the camera. Here is the controls and camera.
<FlyControls ref={flyRef}
enableDamping={false}
movementSpeed={3}
rollSpeed={0.05}
dragToLook={true}
makeDefault={cameraView==0} /> }
<PerspectiveCamera ref={pcRef}
position={new THREE.Vector3(0, 0, 1)}
heightMin={2}
heightMax={2}
fov={45}
makeDefault={cameraView==0}
up={new THREE.Vector3(0,0,1)} />
I tried using the following as part of a useEffect hook:
flyRef.current.target = lookat;
flyRef.current.update();
However, this does not alter the lookat position. I tried placing a lookat property on the initial perspective camera, but this does not do anything either.
So I have very basic setup:
var cubeCamera = new THREE.CubeCamera (1, 1000, 1024);
cubeCamera.renderTarget.texture.minFilter = THREE.LinearMipMapLinearFilter;
cubeCamera.renderTarget.texture.mapping = THREE.CubeRefractionMapping;
cubeCamera.updateCubeMap (renderer, scene);
var matte = new THREE.MeshStandardMaterial({
envMap: cubeCamera.renderTarget.texture,
metalness: 0.5,
roughness: 0.4
});
and this creates correctly blurred refraction. However, driving metalness to 0 makes it vanish almost completely, making the material seem fully opaque. What is correct way to set up matte refractive material?
You are trying to use MeshStandardMaterial to create a translucent and refractive non-metallic material. You are setting metalness to zero, or near zero.
Non-metals typically have a low specular reflectance. That means the specular reflections from the environment are minimal — certainly compared to metals. Consequently, MeshStandardMaterial has been designed to have similar properties.
You have two options.
The first option is to compensate by increasing material.envMapIntensity, which defaults to 1. This simulates a brighter environment.
A second option is to use the more feature-rich MeshPhysicalMaterial, instead.
MeshPhysicalMaterial has an additional material.reflectivity property which controls the specular reflectance for non-metals. For physically-based materials, setting this property to 1 is a reasonable maximum value, but you can increase it further if you want.
three.js r.86