Hello guys, I’m using @react-three /drei and @react-three /fiber packages in my react app, now in my index page there are many rendered 3 objects , they’re displayed in laptop devices but my problem is with mobile , some of them are displayed and some were displayed but after adding new one 3d object they are not displayed (actually there are displayed but in some mobiles)…
It’s is not a problem with code of course ,cause there is not a problem with that and as i said in laptop there are displayed completely fine but they are not in mobile (some devices)
i have tried to use website to make an optimzation for my gltf and texture optimization web but i used it but the same problem …
this my website u can try to open it in both website and mobile if u wanna see portfolio
drcmda
August 1, 2024, 9:55am
2
if each square is a canvas, then that’s not going to work. browsers limit the amount of open webgl contexts to a very small number. drei has a solution for this: GitHub - pmndrs/drei: 🥉 useful helpers for react-three-fiber
you can also look into GitHub - pmndrs/uikit: 🎨 user interfaces for react-three-fiber you can design the whole scroll container in threejs, you don’t even have to use dom/html.
for example this my code of generating tech section in my website
"use client";
import { technologies } from "@/constants";
import React from "react";
import { BallCanvas } from "../canvas";
import { TechnologiesParams } from "@/types";
import SectionWrapper from "@/app/(root)/SectionWrapper";
const Tech: React.FC = (): React.ReactNode => {
return (
<div className="flex flex-wrap justify-center gap-10">
{technologies.map((technology: TechnologiesParams) => (
<div className="w-28 h-28" key={technology.name}>
<BallCanvas icon={technology.icon.src} />
</div>
))}
</div>
);
};
export default SectionWrapper(Tech, "Tech");
"use client";
import {
Decal,
Float,
OrbitControls,
Preload,
useTexture,
} from "@react-three/drei";
import { Canvas } from "@react-three/fiber";
import React, { Suspense } from "react";
import CanvasLoader from "../sections/Loader";
const Ball = ({ imgUrl }: { imgUrl: string }): React.ReactNode => {
const [decal] = useTexture([imgUrl]);
return (
<Float speed={1.75} rotationIntensity={1} floatIntensity={2}>
<ambientLight intensity={0.25} />
<directionalLight position={[0, 0, 0.05]} />
<mesh castShadow receiveShadow scale={2.75}>
<icosahedronGeometry args={[1, 1]} />
<meshStandardMaterial
color={"#fff8eb"}
polygonOffset
polygonOffsetFactor={-5}
flatShading
/>
<Decal
position={[0, 0, 1]}
map={decal}
rotation={[2 * Math.PI, 0, 6.25]}
/>
</mesh>
</Float>
);
};
const BallCanvas = ({ icon }: { icon: string }): React.ReactNode => {
return (
<Canvas
className="top-20"
frameloop="demand"
gl={{ preserveDrawingBuffer: false }}
>
<Suspense fallback={<CanvasLoader />}>
<OrbitControls enableZoom={false} />
<Ball imgUrl={icon} />
</Suspense>
<Preload all />
</Canvas>
);
};
export default BallCanvas;
I inspect white square as u said and yeah like im using canvas for each one . i didnt understand how can i solve my problem , second why it happening only in some mobile not in laptop or some mobiles too
drcmda
August 1, 2024, 11:17pm
4
like i said, browsers arbitrarily limit the amount of open webgl context, i.e. <canvas>
elements. the number may vary from browser to browser, or desktop and mobile. let it be 5, or 10. if you cross over it will start to crash.
it would not even make sense to have 3 canvas, or 2, you should only ever have one single canvas because the memory overhead and performance hit of having multiple is not feasible.
the good news is that this is what drei/view is for, and the rewrite would be simple. it creates a single full screen canvas that is cut into pieces, each piece is isolated into its own scene, camera, controls, etc, this “view” is in your regular dom component graph.
https://codesandbox.io/p/sandbox/view-tracking-bp6tmc
1 Like
i got u , it like create one canvas for all the dom , whole page and instead of displaying each 3d object in canvas i will use View component instead right?
ok what about this one here , im not using a gltf file for rendering ball
"use client";
import { technologies } from "@/constants";
import React from "react";
import { BallCanvas } from "../canvas";
import { TechnologiesParams } from "@/types";
import SectionWrapper from "@/app/(root)/SectionWrapper";
const Tech: React.FC = (): React.ReactNode => {
return (
<div className="flex flex-wrap justify-center gap-10">
{technologies.map((technology: TechnologiesParams) => (
<div className="w-28 h-28" key={technology.name}>
<BallCanvas icon={technology.icon.src} />
</div>
))}
</div>
);
};
export default SectionWrapper(Tech, "Tech");
"use client";
import {
Decal,
Float,
OrbitControls,
Preload,
useTexture,
} from "@react-three/drei";
import { Canvas } from "@react-three/fiber";
import React, { Suspense } from "react";
import CanvasLoader from "../sections/Loader";
const Ball = ({ imgUrl }: { imgUrl: string }): React.ReactNode => {
const [decal] = useTexture([imgUrl]);
return (
<Float speed={1.75} rotationIntensity={1} floatIntensity={2}>
<ambientLight intensity={0.25} />
<directionalLight position={[0, 0, 0.05]} />
<mesh castShadow receiveShadow scale={2.75}>
<icosahedronGeometry args={[1, 1]} />
<meshStandardMaterial
color={"#fff8eb"}
polygonOffset
polygonOffsetFactor={-5}
flatShading
/>
<Decal
position={[0, 0, 1]}
map={decal}
rotation={[2 * Math.PI, 0, 6.25]}
/>
</mesh>
</Float>
);
};
const BallCanvas = ({ icon }: { icon: string }): React.ReactNode => {
return (
<Canvas
className="top-20"
frameloop="demand"
gl={{ preserveDrawingBuffer: false }}
>
<Suspense fallback={<CanvasLoader />}>
<OrbitControls enableZoom={false} />
<Ball imgUrl={icon} />
</Suspense>
<Preload all />
</Canvas>
);
};
export default BallCanvas;
drcmda
August 2, 2024, 12:17pm
6
it isn’t about gltf, but webgl. you can feasibly have one, single webgl canvas. everything on top is a waste of memory and performance, more than a few will crash guaranteed due to arbitrary browser limitations.
drcmda
August 2, 2024, 12:20pm
7
import { Canvas, addEffect } from '@react-three/fiber'
import { View } from '@react-three/drei'
import Lenis from '@studio-freight/lenis'
// Use lenis smooth scroll
const lenis = new Lenis({ syncTouch: true })
// Integrate into fibers own raf loop instead of opening another
addEffect((t) => lenis.raf(t))
const Tech: React.FC = (): React.ReactNode => {
return (
<>
<div className="flex flex-wrap justify-center gap-10">
{technologies.map((technology: TechnologiesParams) => (
<div className="w-28 h-28" key={technology.name}>
<BallCanvas icon={technology.icon.src} />
</div>
))}
</div>
<Canvas
frameloop="demand" gl={{ preserveDrawingBuffer: false }}
style={{ pointerEvents: "none", position: 'fixed', top: 0, bottom: 0, left: 0, right: 0, overflow: 'hidden' }}
eventSource={document.getElementById('root')}
>
<View.Port />
<Preload all />
</Canvas>
</>
)
}
const Ball = ({ imgUrl }: { imgUrl: string }): React.ReactNode => {
const [decal] = useTexture([imgUrl])
return (
<Float speed={1.75} rotationIntensity={1} floatIntensity={2}>
<ambientLight intensity={0.25} />
<directionalLight position={[0, 0, 0.05]} />
<mesh castShadow receiveShadow scale={2.75}>
<icosahedronGeometry args={[1, 1]} />
<meshStandardMaterial color={'#fff8eb'} polygonOffset polygonOffsetFactor={-5} flatShading />
<Decal position={[0, 0, 1]} map={decal} rotation={[2 * Math.PI, 0, 6.25]} />
</mesh>
</Float>
)
}
const BallCanvas = ({ icon }: { icon: string }): React.ReactNode => {
return (
<View className="top-20">
<OrbitControls enableZoom={false} />
<Ball imgUrl={icon} />
</View>
)
}
i make the body element as the root , and i did what u said
"use client";
import { technologies } from "@/constants";
import { TechnologiesParams } from "@/types";
import { Canvas } from "@react-three/fiber";
import { Preload, View } from "@react-three/drei";
import React, { useEffect, useState } from "react";
import SectionWrapper from "@/app/(root)/SectionWrapper";
import { BallCanvas } from "../canvas";
const Tech: React.FC = () => {
const [eventSource, setEventSource] = useState<HTMLElement | undefined>(
undefined
);
useEffect(() => {
const rootElement = document.getElementById("root");
if (rootElement) {
setEventSource(rootElement);
}
}, []);
return (
<>
<div className="flex flex-wrap justify-center gap-10">
{technologies.map((technology: TechnologiesParams) => (
<div className="w-28 h-28" key={technology.name}>
<BallCanvas icon={technology.icon.src} />
</div>
))}
</div>
<Canvas
frameloop="demand"
gl={{ preserveDrawingBuffer: false }}
style={{
position: "fixed",
top: 0,
bottom: 0,
left: 0,
right: 0,
overflow: "hidden",
}}
eventSource={eventSource}
>
<View.Port />
<Preload all />
</Canvas>
</>
);
};
export default SectionWrapper(Tech, "Tech");
"use client";
import {
Decal,
Float,
OrbitControls,
useTexture,
View,
} from "@react-three/drei";
import React from "react";
interface BallProps {
imgUrl: string;
}
const Ball: React.FC<BallProps> = ({ imgUrl }) => {
const [decal] = useTexture([imgUrl]);
return (
<Float speed={1.75} rotationIntensity={1} floatIntensity={2}>
<ambientLight intensity={0.25} />
<directionalLight position={[0, 0, 0.05]} />
<mesh castShadow receiveShadow scale={2.75}>
<icosahedronGeometry args={[1, 1]} />
<meshStandardMaterial
color={"#fff8eb"}
polygonOffset
polygonOffsetFactor={-5}
flatShading
/>
<Decal
position={[0, 0, 1]}
map={decal}
rotation={[2 * Math.PI, 0, 6.25]}
/>
</mesh>
</Float>
);
};
interface BallCanvasProps {
icon: string;
}
const BallCanvas: React.FC<BallCanvasProps> = ({ icon }) => {
return (
<View className="top-20">
<OrbitControls enableZoom={false} />
<Ball imgUrl={icon} />
</View>
);
};
export default BallCanvas;