Skip to content

Instantly share code, notes, and snippets.

@myselfuser1
Created August 4, 2023 04:39
Show Gist options
  • Save myselfuser1/86b1821d28a3d21bc51acf517ea1e1b2 to your computer and use it in GitHub Desktop.
Save myselfuser1/86b1821d28a3d21bc51acf517ea1e1b2 to your computer and use it in GitHub Desktop.
"use client";
import { useCallback, useRef, useState } from "react";
import * as THREE from "three";
// import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import Stats from "stats.js";
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
import { gsap } from "gsap";
import styles from "./page.module.css";
const MyCanvas = () => {
const loadingBarRef = useRef(null);
// const [progressRatio, setProgressBarRatio] = useState(0);
const canvasRef = useCallback((node) => {
if (node != null) {
const scene = new THREE.Scene();
const stats = new Stats();
stats.showPanel(0);
document.body.appendChild(stats.dom);
const overlayGeometry = new THREE.PlaneGeometry(2, 2, 1, 1);
const overlayMaterial = new THREE.ShaderMaterial({
transparent: true,
uniforms: {
uAlpha: {
value: 1,
},
},
vertexShader: `
void main()
{
gl_Position = vec4(position, 1.0);
}
`,
fragmentShader: `
uniform float uAlpha;
void main(){
gl_FragColor = vec4(0.0,0.0,0.0,uAlpha);
}
`,
});
const overlay = new THREE.Mesh(overlayGeometry, overlayMaterial);
const loadingManager = new THREE.LoadingManager(
() => {
console.log("loaded");
window.setTimeout(() => {}, 500);
gsap.delayedCall(0.5, () => {
gsap.to(overlayMaterial.uniforms.uAlpha, { value: 0, duration: 3 });
if (loadingBarRef.current !== null) {
loadingBarRef.current.style.transform = "";
loadingBarRef.current.style.transformOrigin = "top right";
loadingBarRef.current.style.transition = "1.5s ease-in-out";
}
});
},
(itemUrl, itemsLoaded, itemsTotal) => {
const progressRatio = itemsLoaded / itemsTotal;
// setProgressBarRatio(itemsLoaded / itemsTotal);
if (loadingBarRef.current !== null) {
console.log("in progresss");
loadingBarRef.current.style.transform = `scaleX(${progressRatio})`;
// loadingBarRef.current.style.backgroundColor = "blue";
console.log(progressRatio);
}
}
);
const gltfLoader = new GLTFLoader(loadingManager);
const cubeTextureLoader = new THREE.CubeTextureLoader(loadingManager);
const environmentMap = cubeTextureLoader.load([
"/textures/environmentMaps/0/px.jpg",
"/textures/environmentMaps/0/nx.jpg",
"/textures/environmentMaps/0/py.jpg",
"/textures/environmentMaps/0/ny.jpg",
"/textures/environmentMaps/0/pz.jpg",
"/textures/environmentMaps/0/nz.jpg",
]);
scene.background = environmentMap;
scene.environment = environmentMap;
const updateAllMaterials = () => {
scene.traverse((child) => {
if (
child instanceof THREE.Mesh &&
child.material instanceof THREE.MeshStandardMaterial
) {
// child.material.envMap = environmentMap
child.material.envMapIntensity = 2.5;
child.material.needsUpdate = true;
child.castShadow = true;
child.receiveShadow = true;
}
});
};
gltfLoader.load("/models/FlightHelmet/glTF/FlightHelmet.gltf", (gltf) => {
gltf.scene.scale.set(10, 10, 10);
gltf.scene.position.set(0, -4, 0);
gltf.scene.rotation.y = Math.PI * 0.5;
scene.add(gltf.scene);
updateAllMaterials();
});
const directionalLight = new THREE.DirectionalLight("#ffffff", 3);
directionalLight.castShadow = true;
directionalLight.shadow.camera.far = 15;
directionalLight.shadow.mapSize.set(1024, 1024);
directionalLight.shadow.normalBias = 0.05;
directionalLight.position.set(0.25, 3, -2.25);
scene.add(directionalLight);
scene.add(overlay);
const sizes = {
width: window.innerWidth,
height: window.innerHeight,
};
// Camera
const camera = new THREE.PerspectiveCamera(
75,
sizes.width / sizes.height,
0.1,
100
);
camera.position.set(4, 1, -4);
scene.add(camera);
const controls = new OrbitControls(camera, node);
controls.enableDamping = true;
// Renderer
const renderer = new THREE.WebGLRenderer({
canvas: node,
powerPreference: "high-performance",
antialias: true,
});
renderer.toneMapping = THREE.ReinhardToneMapping;
renderer.toneMappingExposure = 3;
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.setSize(sizes.width, sizes.height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
window.addEventListener("resize", () => {
sizes.width = window.innerWidth;
sizes.height = window.innerHeight;
camera.aspect = sizes.width / sizes.height;
camera.updateProjectionMatrix();
renderer.setSize(sizes.width, sizes.height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
});
window.addEventListener("dblclick", () => {
const fullscreenElement =
document.fullscreenElement || document.webkitFullscreenElement;
if (!fullscreenElement) {
if (node.requestFullscreen) {
node.requestFullscreen();
} else if (canvasRef.webkitRequestFullscreen) {
node.webkitRequestFullscreen();
}
} else {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
}
}
});
const clock = new THREE.Clock();
const tick = () => {
stats.begin();
const elapsedTime = clock.getElapsedTime();
controls.update();
renderer.render(scene, camera);
window.requestAnimationFrame(tick);
stats.end();
};
tick();
}
}, []);
return (
<>
<div
ref={loadingBarRef}
className="loading-bar"
style={{
position: "absolute",
top: "50%",
width: "100%",
height: "2px",
background: "black",
transform: `scaleX(0)`,
transformOrigin: "top left",
transition: "transform 0.5s",
willChange: "transform",
}}
></div>
<canvas
style={{ position: "fixed", top: 0, left: 0, outline: "none" }}
ref={canvasRef}
className="webgl"
></canvas>
</>
);
};
export default MyCanvas;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment