category: prog, direction: js, group: threejs
Three.js
Three.js

источник: Creating the Effect of Transparent Glass and Plastic in Three.js
ключи: #threejs
Ключи: #3d, #js
только важные выдержки
google query: tree js semi transparent sphere
Creating the Effect of Transparent Glass and Plastic in Three.js
const canvasSketch = require("canvas-sketch");
// Import ThreeJS and assign it to global scope
// This way examples/ folder can use it too
const THREE = require("three");
global.THREE = THREE;
// Import extra THREE plugins
require("three/examples/js/controls/OrbitControls");
require("three/examples/js/geometries/RoundedBoxGeometry.js");
require("three/examples/js/loaders/GLTFLoader.js");
require("three/examples/js/loaders/RGBELoader.js");
const Stats = require("stats-js");
const { GUI } = require("dat.gui");
const settings = {
animate: true,
context: "webgl",
resizeCanvas: false
};
const sketch = ({ context, canvas }) => {
const stats = new Stats();
document.body.appendChild(stats.dom);
const gui = new GUI();
const options = {
enableSwoopingCamera: false,
enableRotation: true,
transmission: 1,
thickness: 1.2,
roughness: 0.6,
envMapIntensity: 1.5,
clearcoat: 1,
clearcoatRoughness: 0.1,
normalScale: 1,
clearcoatNormalScale: 0.3,
normalRepeat: 1
};
// Setup
// -----
const renderer = new THREE.WebGLRenderer({
context,
antialias: false
});
renderer.setClearColor(0x1f1e1c, 1);
const camera = new THREE.PerspectiveCamera(45, 1, 0.01, 100);
camera.position.set(0, 0, 5);
const controls = new THREE.OrbitControls(camera, canvas);
controls.enabled = !options.enableSwoopingCamera;
const scene = new THREE.Scene();
// Content
// -------
const textureLoader = new THREE.TextureLoader();
const bgTexture = textureLoader.load("src/texture.jpg");
const bgGeometry = new THREE.PlaneGeometry(5, 5);
const bgMaterial = new THREE.MeshBasicMaterial({ map: bgTexture });
const bgMesh = new THREE.Mesh(bgGeometry, bgMaterial);
bgMesh.position.set(0, 0, -1);
scene.add(bgMesh);
const positions = [
[-0.85, 0.85, 0],
[0.85, 0.85, 0],
[-0.85, -0.85, 0],
[0.85, -0.85, 0]
];
const geometries = [
new THREE.IcosahedronGeometry(0.75, 0), // Faceted
new THREE.IcosahedronGeometry(0.67, 24), // Sphere
new THREE.RoundedBoxGeometry(1.12, 1.12, 1.12, 16, 0.2)
];
const hdrEquirect = new THREE.RGBELoader().load(
"src/empty_warehouse_01_2k.hdr",
() => {
hdrEquirect.mapping = THREE.EquirectangularReflectionMapping;
}
);
const normalMapTexture = textureLoader.load("src/normal.jpg");
normalMapTexture.wrapS = THREE.RepeatWrapping;
normalMapTexture.wrapT = THREE.RepeatWrapping;
normalMapTexture.repeat.set(options.normalRepeat, options.normalRepeat);
const material = new THREE.MeshPhysicalMaterial({
transmission: options.transmission,
thickness: options.thickness,
roughness: options.roughness,
envMap: hdrEquirect,
envMapIntensity: options.envMapIntensity,
clearcoat: options.clearcoat,
clearcoatRoughness: options.clearcoatRoughness,
normalScale: new THREE.Vector2(options.normalScale),
normalMap: normalMapTexture,
clearcoatNormalMap: normalMapTexture,
clearcoatNormalScale: new THREE.Vector2(options.clearcoatNormalScale)
});
const meshes = geometries.map(
(geometry) => new THREE.Mesh(geometry, material)
);
meshes.forEach((mesh, i) => {
scene.add(mesh);
mesh.position.set(...positions[i]);
});
// Add dragon GLTF model
new THREE.GLTFLoader().load("src/dragon.glb", (gltf) => {
const dragon = gltf.scene.children.find((mesh) => mesh.name === "Dragon");
// Just copy the geometry from the loaded model
const geometry = dragon.geometry.clone();
// Adjust geometry to suit our scene
geometry.rotateX(Math.PI / 2);
geometry.translate(0, -4, 0);
// Create a new mesh and place it in the scene
const mesh = new THREE.Mesh(geometry, material);
mesh.position.set(...positions[3]);
mesh.scale.set(0.135, 0.135, 0.135);
meshes.push(mesh);
scene.add(mesh);
// Discard the model
dragon.geometry.dispose();
dragon.material.dispose();
});
// GUI
// ---
gui.add(options, "enableSwoopingCamera").onChange((val) => {
controls.enabled = !val;
controls.reset();
});
gui.add(options, "enableRotation").onChange(() => {
meshes.forEach((mesh) => mesh.rotation.set(0, 0, 0));
});
gui.add(options, "transmission", 0, 1, 0.01).onChange((val) => {
material.transmission = val;
});
gui.add(options, "thickness", 0, 5, 0.1).onChange((val) => {
material.thickness = val;
});
gui.add(options, "roughness", 0, 1, 0.01).onChange((val) => {
material.roughness = val;
});
gui.add(options, "envMapIntensity", 0, 3, 0.1).onChange((val) => {
material.envMapIntensity = val;
});
gui.add(options, "clearcoat", 0, 1, 0.01).onChange((val) => {
material.clearcoat = val;
});
gui.add(options, "clearcoatRoughness", 0, 1, 0.01).onChange((val) => {
material.clearcoatRoughness = val;
});
gui.add(options, "normalScale", 0, 5, 0.01).onChange((val) => {
material.normalScale.set(val, val);
});
gui.add(options, "clearcoatNormalScale", 0, 5, 0.01).onChange((val) => {
material.clearcoatNormalScale.set(val, val);
});
gui.add(options, "normalRepeat", 1, 4, 1).onChange((val) => {
normalMapTexture.repeat.set(val, val);
});
// Update
// ------
const update = (time, deltaTime) => {
const ROTATE_TIME = 10; // Time in seconds for a full rotation
const xAxis = new THREE.Vector3(1, 0, 0);
const yAxis = new THREE.Vector3(0, 1, 0);
const rotateX = (deltaTime / ROTATE_TIME) * Math.PI * 2;
const rotateY = (deltaTime / ROTATE_TIME) * Math.PI * 2;
if (options.enableRotation) {
meshes.forEach((mesh) => {
mesh.rotateOnWorldAxis(xAxis, rotateX);
mesh.rotateOnWorldAxis(yAxis, rotateY);
});
}
if (options.enableSwoopingCamera) {
camera.position.x = Math.sin((time / 10) * Math.PI * 2) * 2;
camera.position.y = Math.cos((time / 10) * Math.PI * 2) * 2;
camera.position.z = 4;
camera.lookAt(scene.position);
}
};
// Lifecycle
// ---------
return {
resize({ canvas, pixelRatio, viewportWidth, viewportHeight }) {
const dpr = Math.min(pixelRatio, 2); // Cap DPR scaling to 2x
canvas.width = viewportWidth * dpr;
canvas.height = viewportHeight * dpr;
canvas.style.width = viewportWidth + "px";
canvas.style.height = viewportHeight + "px";
renderer.setPixelRatio(dpr);
renderer.setSize(viewportWidth, viewportHeight);
camera.aspect = viewportWidth / viewportHeight;
camera.updateProjectionMatrix();
},
render({ time, deltaTime }) {
stats.begin();
controls.update();
update(time, deltaTime);
renderer.render(scene, camera);
stats.end();
},
unload() {
geometries.forEach((geometry) => geometry.dispose());
material.dispose();
hdrEquirect.dispose();
controls.dispose();
renderer.dispose();
gui.destroy();
document.body.removeChild(stats.dom);
}
};
};
canvasSketch(sketch, settings);