three.js之加载模型、贴图
加载各种模型
<canvas id="mainCanvas"></canvas>
<script type="importmap">
{
"imports": {
"three": "./js/build/three.module.js",
"three/addons/": "./js/jsm/"
}
}
</script>
<script type="module">
import * as THREE from "three";
import { TrackballControls } from "three/addons/controls/TrackballControls.js";
import { GUI } from "three/addons/libs/lil-gui.module.min.js";
import { initRenderer, initPerspectiveCamera, initAmbientLight, initSpotLight } from "./init.js";
import { OBJLoader } from "three/addons/loaders/OBJLoader.js";
import { MTLLoader } from "three/addons/loaders/MTLLoader.js";
import { ColladaLoader } from "three/addons/loaders/ColladaLoader.js";
import { STLLoader } from "three/addons/loaders/STLLoader.js";
import { VTKLoader } from "three/addons/loaders/VTKLoader.js";
import { PDBLoader } from "three/addons/loaders/PDBLoader.js";
import { PLYLoader } from "three/addons/loaders/PLYLoader.js";
import { VRMLLoader } from "three/addons/loaders/VRMLLoader.js";
import { TDSLoader } from "three/addons/loaders/TDSLoader.js";
import { ThreeMFLoader } from "three/addons/loaders/3MFLoader.js";
import { AMFLoader } from "three/addons/loaders/AMFLoader.js";
import { DRACOLoader } from "three/addons/loaders/DRACOLoader.js";
import { GCodeLoader } from "three/addons/loaders/GCodeLoader.js";
import { SVGLoader } from "three/addons/loaders/SVGLoader.js";
import { FBXLoader } from "three/addons/loaders/FBXLoader.js";
function init() {
const gui = new GUI();
const renderer = initRenderer("mainCanvas");
let scene = new THREE.Scene();
const camera = initPerspectiveCamera();
scene.add(camera);
const ambientLight = initAmbientLight();
scene.add(ambientLight);
const spotLight = initSpotLight();
scene.add(spotLight);
let knot = createMesh(new THREE.TorusKnotGeometry(10, 1, 64, 8, 2, 3));
scene.add(knot);
const controls = setupControls();
let step = 0;
let loadedMesh;
render();
function render() {
knot.rotation.y = step += 0.01;
requestAnimationFrame(render);
renderer.render(scene, camera);
}
function setupControls() {
const controls = new (function () {
this.radius = knot.geometry.parameters.radius;
this.tube = 0.3;
this.radialSegments = knot.geometry.parameters.radialSegments;
this.tubularSegments = knot.geometry.parameters.tubularSegments;
this.p = knot.geometry.parameters.p;
this.q = knot.geometry.parameters.q;
this.redraw = function () {
scene.remove(knot);
knot = createMesh(
new THREE.TorusKnotGeometry(controls.radius, controls.tube, Math.round(controls.radialSegments), Math.round(controls.tubularSegments), Math.round(controls.p), Math.round(controls.q))
);
scene.add(knot);
};
this.saveMesh = function () {
const result = knot.toJSON();
sessionStorage.setItem("mesh", JSON.stringify(result));
console.log(sessionStorage.getItem("mesh"));
};
this.loadMesh = function () {
scene.remove(loadedMesh);
const json = sessionStorage.getItem("mesh");
if (json) {
const loadedGeometry = JSON.parse(json);
const loader = new THREE.ObjectLoader();
loadedMesh = loader.parse(loadedGeometry);
loadedMesh.position.x -= 40;
scene.add(loadedMesh);
}
};
this.exportScene = function () {
sessionStorage.setItem("scene", JSON.stringify(scene.toJSON()));
console.log(sessionStorage.getItem("scene"));
};
this.clearScene = function () {
scene = new THREE.Scene();
scene.add(ambientLight);
scene.add(spotLight);
};
this.importScene = function () {
const json = sessionStorage.getItem("scene");
if (json) {
const loadedSceneAsJson = JSON.parse(json);
const loader = new THREE.ObjectLoader();
scene = loader.parse(loadedSceneAsJson);
}
};
this.loadFromJson = function () {
const loader = new THREE.ObjectLoader();
loader.load("./models/lightmap/lightmap.json", function (obj) {
computeSize(obj);
console.log("obj scale", obj.scale);
computeSize(scene);
obj.scale.set(5, 5, 5);
scene.add(obj);
});
};
this.loadFromObj = function () {
// OBJ加载器 用于加载 .obj 资源的加载器。
// OBJ 文件格式是一种简单的数据格式, 这种格式以人类可读的形式来表示3D几何体,即每个顶点的位置、每个纹理坐标顶点的UV位置、顶点法线、 将使每个多边形定义为顶点列表的面以及纹理顶点。
const loader = new OBJLoader();
loader.load("./models/tree.obj", function (obj) {
computeSize(obj);
console.log("obj scale", obj.scale);
computeSize(scene);
obj.scale.set(20, 20, 20);
scene.add(obj);
});
};
this.loadFromObjMtl = function () {
const mtlLoader = new MTLLoader();
mtlLoader.load("./models/walt/WaltHead.mtl", function (materials) {
materials.preload();
const loader = new OBJLoader();
loader.load("./models/walt/WaltHead.obj", function (obj) {
computeSize(obj);
console.log("obj scale", obj.scale);
computeSize(scene);
obj.scale.set(0.2, 0.2, 0.2);
scene.add(obj);
});
});
};
this.loadFromCollada = function () {
const loader = new ColladaLoader();
loader.load("./models/collada/elf/elf.dae", function (res) {
console.log(res);
computeSize(res.scene);
res.scene.scale.set(2, 2, 2);
scene.add(res.scene);
});
};
this.loadFromStl = function () {
const loader = new STLLoader();
loader.load("./models/stl/ascii/slotted_disk.stl", function (geometry) {
const mat = new THREE.MeshStandardMaterial({
color: 0xffffff,
metalness: 1,
roughness: 0.5,
});
const mesh = new THREE.Mesh(geometry, mat);
mesh.rotation.x = -0.5 * Math.PI;
mesh.scale.set(20, 20, 20);
computeSize(mesh);
computeSize(scene);
scene.add(mesh);
});
};
this.loadFromVtk = function () {
const loader = new VTKLoader();
loader.load("./models/vtk/liver.vtk", function (geometry) {
const mat = new THREE.MeshNormalMaterial();
geometry.center();
geometry.computeVertexNormals();
const mesh = new THREE.Mesh(geometry, mat);
mesh.scale.set(0.3, 0.3, 0.3);
computeSize(mesh);
computeSize(scene);
scene.add(mesh);
});
};
this.loadFromPdb = function () {
const loader = new PDBLoader();
loader.load("./models/diamond.pdb", function (geometries) {
const group = new THREE.Object3D();
const geometryAtoms = geometries.geometryAtoms;
for (let i = 0; i < geometryAtoms.attributes.position.count; i++) {
const startPosition = new THREE.Vector3();
startPosition.x = geometryAtoms.attributes.position.getX(i);
startPosition.y = geometryAtoms.attributes.position.getY(i);
startPosition.z = geometryAtoms.attributes.position.getZ(i);
const color = new THREE.Color();
color.r = geometryAtoms.attributes.color.getX(i);
color.g = geometryAtoms.attributes.color.getY(i);
color.b = geometryAtoms.attributes.color.getZ(i);
const material = new THREE.MeshPhongMaterial({
color: color,
});
const sphere = new THREE.SphereGeometry(0.2);
const mesh = new THREE.Mesh(sphere, material);
mesh.position.copy(startPosition);
group.add(mesh);
}
const geometryBonds = geometries.geometryBonds;
for (let j = 0; j < geometryBonds.attributes.position.count; j += 2) {
const startPosition = new THREE.Vector3();
startPosition.x = geometryBonds.attributes.position.getX(j);
startPosition.y = geometryBonds.attributes.position.getY(j);
startPosition.z = geometryBonds.attributes.position.getZ(j);
const endPosition = new THREE.Vector3();
endPosition.x = geometryBonds.attributes.position.getX(j + 1);
endPosition.y = geometryBonds.attributes.position.getY(j + 1);
endPosition.z = geometryBonds.attributes.position.getZ(j + 1);
const path = new THREE.CatmullRomCurve3([startPosition, endPosition]);
const tube = new THREE.TubeGeometry(path, 1, 0.04);
const material = new THREE.MeshPhongMaterial({
color: 0xcccccc,
});
const mesh = new THREE.Mesh(tube, material);
group.add(mesh);
}
computeSize(scene);
computeSize(group);
group.scale.set(2, 2, 2);
scene.add(group);
});
};
this.loadFromPly = function () {
const loader = new PLYLoader();
loader.load("./models/ply/ascii/dolphins.ply", function (geometry) {
const material = new THREE.PointsMaterial({
color: 0xffffff,
size: 1,
opacity: 0.6,
transparent: true,
blending: THREE.AdditiveBlending,
depthWrite: false,
map: generateSprite(),
});
const group = new THREE.Points(geometry, material);
group.scale.set(0.05, 0.05, 0.05);
computeSize(scene);
computeSize(group);
scene.add(group);
});
};
this.loadFromVrml = function () {
const loader = new VRMLLoader();
loader.load("./models/house.wrl", function (model) {
computeSize(model);
console.log;
computeSize(scene);
model.scale.set(2, 2, 2);
scene.add(model);
});
};
this.loadFromTds = function () {
const loader = new TDSLoader();
loader.load("./models/3ds/portalgun/portalgun.3ds", function (group) {
computeSize(group);
group.scale.set(20, 20, 20);
scene.add(group);
});
};
this.loadFrom3mf = function () {
const loader = new ThreeMFLoader();
loader.load("./models/truck.3mf", function (group) {
computeSize(group);
scene.add(group);
});
};
this.loadFromAmf = function () {
const loader = new AMFLoader();
loader.load("./models/rook.amf", function (group) {
computeSize(group);
group.scale.set(5, 5, 5);
scene.add(group);
});
};
this.loadFromDrc = function () {
// DRACOLoader 一个用于加载经过Draco压缩的图形库。
// Draco是一个开源的库,主要用于压缩和解压缩三维模型及点云。 以客户端上解压缩为代价,显著减少压缩的图形。
// 独立的Draco文件后缀为.drc,其中包含顶点坐标,法线,颜色和其他的属性,不包含材质,纹理,动画和节点结构。
const loader = new DRACOLoader();
loader.setDecoderPath("./js/jsm/libs/draco/");
loader.setDecoderConfig({ type: "js" });
loader.preload();
loader.load("./models/bunny.drc", function (geometry) {
geometry.computeVertexNormals();
geometry.computeBoundingSphere();
geometry.computeBoundingBox();
const mesh = new THREE.Mesh(geometry, new THREE.MeshNormalMaterial());
computeSize(mesh);
mesh.scale.set(100, 100, 100);
scene.add(mesh);
});
};
this.loadFromGcode = function () {
const loader = new GCodeLoader();
loader.load("./models/benchy.gcode", function (obj) {
computeSize(obj);
obj.scale.set(0.1, 0.1, 0.1);
scene.add(obj);
});
};
this.loadFromSvg = function () {
// SVGLoader 用于加载.svg资源的加载器
// 可伸缩向量图形是XML形式的矢量图形格式,用来描述二维矢量图形并支持交互和动画。
const loader = new SVGLoader();
loader.load("./models/tiger.svg", function (data) {
const paths = data.paths;
const group = new THREE.Group();
group.scale.multiplyScalar(0.1);
group.scale.y *= -1;
for (let i = 0; i < paths.length; i++) {
const path = paths[i];
const material = new THREE.MeshBasicMaterial({
color: path.color,
side: THREE.DoubleSide,
depthWrite: false,
});
const shapes = path.toShapes(true);
for (let j = 0; j < shapes.length; j++) {
const shape = shapes[j];
const geometry = new THREE.ShapeGeometry(shape);
const mesh = new THREE.Mesh(geometry, material);
group.add(mesh);
}
}
computeSize(group);
scene.add(group);
});
};
this.loadFromFbx = function () {
const fbxloader = new FBXLoader();
fbxloader.load("./models/Samba Dancing.fbx", function (obj) {
console.log(obj);
computeSize(obj);
obj.scale.set(0.1, 0.1, 0.1);
scene.add(obj);
});
};
})();
const ioGui = gui.addFolder("Save & Load");
ioGui.add(controls, "exportScene");
ioGui.add(controls, "clearScene");
ioGui.add(controls, "importScene");
ioGui.add(controls, "saveMesh");
ioGui.add(controls, "loadMesh");
ioGui.add(controls, "loadFromJson");
ioGui.add(controls, "loadFromObj");
ioGui.add(controls, "loadFromObjMtl");
ioGui.add(controls, "loadFromCollada");
ioGui.add(controls, "loadFromStl");
ioGui.add(controls, "loadFromVtk");
ioGui.add(controls, "loadFromPdb");
ioGui.add(controls, "loadFromPly");
ioGui.add(controls, "loadFromVrml");
ioGui.add(controls, "loadFromTds");
ioGui.add(controls, "loadFrom3mf");
ioGui.add(controls, "loadFromAmf");
ioGui.add(controls, "loadFromDrc");
ioGui.add(controls, "loadFromGcode");
ioGui.add(controls, "loadFromSvg");
ioGui.add(controls, "loadFromFbx");
const meshGui = gui.addFolder("mesh");
meshGui.add(controls, "radius", 0, 40).onChange(controls.redraw);
meshGui.add(controls, "tube", 0, 40).onChange(controls.redraw);
meshGui.add(controls, "radialSegments", 1, 400).step(1).onChange(controls.redraw);
meshGui.add(controls, "tubularSegments", 1, 20).step(1).onChange(controls.redraw);
meshGui.add(controls, "p", 1, 10).step(1).onChange(controls.redraw);
meshGui.add(controls, "q", 1, 15).step(1).onChange(controls.redraw);
return controls;
}
}
init();
function createMesh(geom) {
const meshMaterial = new THREE.MeshBasicMaterial({
vertexColors: false,
wireframe: true,
wireframeLinewidth: 2,
color: 0xaaaaaa,
});
meshMaterial.side = THREE.DoubleSide;
const mesh = new THREE.Mesh(geom, meshMaterial);
mesh.position.set(20, 0, 0);
return mesh;
}
function computeSize(obj) {
const cbox = new THREE.Box3().setFromObject(obj);
const size = cbox.getSize(new THREE.Vector3());
if (obj instanceof THREE.Scene) {
console.log("scene size", size);
} else {
console.log("obj size", size);
}
}
function generateSprite() {
const canvas = document.createElement("canvas");
canvas.width = 16;
canvas.height = 16;
const context = canvas.getContext("2d");
const gradient = context.createRadialGradient(canvas.width / 2, canvas.height / 2, 0, canvas.width / 2, canvas.height / 2, canvas.width / 2);
gradient.addColorStop(0, "rgba(255,255,255,1)");
gradient.addColorStop(0.2, "rgba(0,255,255,1)");
gradient.addColorStop(0.4, "rgba(0,0,64,1)");
gradient.addColorStop(1, "rgba(0,0,0,1)");
context.fillStyle = gradient;
context.fillRect(0, 0, canvas.width, canvas.height);
const texture = new THREE.Texture(canvas);
texture.needsUpdate = true;
return texture;
}
</script>
加载贴图
<canvas id="mainCanvas"></canvas>
<script type="importmap">
{
"imports": {
"three": "./js/build/three.module.js",
"three/addons/": "./js/jsm/"
}
}
</script>
<script type="module">
import * as THREE from "three";
import { GUI } from "three/addons/libs/lil-gui.module.min.js";
import { TrackballControls } from "three/addons/controls/TrackballControls.js";
import { DDSLoader } from "three/addons/loaders/DDSLoader.js";
import { PVRLoader } from "three/addons/loaders/PVRLoader.js";
import { TGALoader } from "three/addons/loaders/TGALoader.js";
import { KTXLoader } from "three/addons/loaders/KTXLoader.js";
import { EXRLoader } from "three/addons/loaders/EXRLoader.js";
import { RGBELoader } from "three/addons/loaders/RGBELoader.js";
import { initRenderer, initPerspectiveCamera, initAmbientLight, initSpotLight, addPlane, addMaterialSettings, addSpecificMaterialSettings } from "./init.js";
function init() {
const gui = new GUI();
const renderer = initRenderer("mainCanvas");
let scene = new THREE.Scene();
const camera = initPerspectiveCamera();
scene.add(camera);
const ambientLight = initAmbientLight();
scene.add(ambientLight);
const spotLight = initSpotLight();
scene.add(spotLight);
const axesHelper = new THREE.AxesHelper(150);
scene.add(axesHelper);
const trackballControls = new TrackballControls(camera, renderer.domElement);
const groundPlane = addPlane({ width: 200, height: 200 });
groundPlane.position.set(0, -10, 0);
scene.add(groundPlane);
const textureLoader = new THREE.TextureLoader();
let meshs = addGeometrys([
textureLoader.load("./textures/general/metal-rust.jpg"),
textureLoader.load("./textures/general/floor-wood.jpg"),
textureLoader.load("./textures/general/brick-wall.jpg"),
]);
const controls = setupControls();
const clock = new THREE.Clock();
render();
function render() {
trackballControls.update(clock.getDelta());
for (let i in meshs) {
if (i == 0) {
meshs[i].rotation.x += 0.01;
} else if (i == meshs.length - 1) {
meshs[i].rotation.z += 0.01;
} else {
meshs[i].rotation.y += 0.01;
}
}
let cubeCamera = null;
scene.traverse(function (obj) {
if (obj instanceof THREE.CubeCamera) {
cubeCamera = obj;
}
});
if (cubeCamera != null) {
meshs[0].visible = false;
cubeCamera.update(renderer, scene);
meshs[1].visible = true;
}
requestAnimationFrame(render);
renderer.render(scene, camera);
}
function addGeometrys(textures) {
const geoms = [new THREE.IcosahedronGeometry(8, 0), new THREE.SphereGeometry(5, 20, 20), new THREE.BoxGeometry(10, 10, 10)];
const meshs = [];
if (textures.length == 3) {
for (let i in textures) {
//map : Texture 颜色贴图。可以选择包括一个alpha通道,通常与.transparent 或.alphaTest。默认为null。 纹理贴图颜色由漫反射颜色.color调节。
const mat = new THREE.MeshStandardMaterial({
map: textures[i],
metalness: 0.2,
roughness: 0.07,
});
const mesh = new THREE.Mesh(geoms[i], mat);
mesh.castShadow = true;
scene.add(mesh);
meshs.push(mesh);
}
} else if (textures.length == 1) {
for (let i in geoms) {
const mat = new THREE.MeshStandardMaterial({
map: textures[0],
metalness: 0.2,
roughness: 0.07,
});
const mesh = new THREE.Mesh(geoms[i], mat);
mesh.castShadow = true;
scene.add(mesh);
meshs.push(mesh);
}
} else if (textures.length == 0) {
for (let i in geoms) {
const mat = new THREE.MeshStandardMaterial({
color: 0x00ffff,
metalness: 0.2,
roughness: 0.07,
});
const mesh = new THREE.Mesh(geoms[i], mat);
mesh.castShadow = true;
scene.add(mesh);
meshs.push(mesh);
}
}
for (let i in meshs) {
if (i == 0) {
meshs[i].position.x = -20;
} else if (i == meshs.length - 1) {
meshs[i].position.x = 20;
}
}
return meshs;
}
function setupControls() {
const controls = new (function () {
this.clearScene = function () {
scene = new THREE.Scene();
scene.add(ambientLight);
scene.add(spotLight);
scene.add(groundPlane);
};
this.loadDds = function () {
for (let i in meshs) {
scene.remove(meshs[i]);
}
const textureLoader = new DDSLoader();
const texture = textureLoader.load("./textures/dds/test-dxt1.dds");
meshs = addGeometrys([texture]);
};
this.loadPvr = function () {
for (let i in meshs) {
scene.remove(meshs[i]);
}
console.log("pvrtc", renderer.extensions.get("WEBGL_compressed_texture_pvrtc"));
const textureLoader = new PVRLoader();
const texture = textureLoader.load("./textures/pvr/tex_base.pvr"); //显示纯黑色,似乎贴图未加载
meshs = addGeometrys([texture]);
};
this.loadTga = function () {
for (let i in meshs) {
scene.remove(meshs[i]);
}
const textureLoader = new TGALoader();
meshs = addGeometrys([textureLoader.load("./textures/tga/dried_grass.tga"), textureLoader.load("./textures/tga/grass.tga"), textureLoader.load("./textures/tga/moss.tga")]);
};
this.loadKtx = function () {
for (let i in meshs) {
scene.remove(meshs[i]);
}
const textureLoader = new KTXLoader();
const format = determineFormat();
console.log(format);
let texture;
switch (format) {
case "astc":
texture = textureLoader.load("./textures/ktx/disturb_ASTC4x4.ktx");
break;
case "etc1":
texture = textureLoader.load("./textures/ktx/disturb_ETC1.ktx");
break;
case "s3tc":
texture = textureLoader.load("./textures/ktx/disturb_BC1.ktx");
break;
case "pvrtc":
texture = textureLoader.load("./textures/ktx/disturb_PVR2bpp.ktx");
break;
}
meshs = addGeometrys([texture]);
};
this.loadExr = function () {
for (let i in meshs) {
scene.remove(meshs[i]);
}
const textureLoader = new EXRLoader();
const texture = textureLoader.load("./textures/exr/Rec709.exr");
meshs = addGeometrys([texture]);
};
this.loadRgbe = function () {
for (let i in meshs) {
scene.remove(meshs[i]);
}
const textureLoader = new RGBELoader();
textureLoader.load("./textures/hdr/dani_cathedral_oBBC.hdr", function (texture) {
texture.flipY = true;
meshs = addGeometrys([texture]);
});
};
this.loadBumpmap = function () {
for (let i in meshs) {
scene.remove(meshs[i]);
}
// 用于创建凹凸贴图的纹理。黑色和白色值映射到与光照相关的感知深度。
// 凹凸实际上不会影响对象的几何形状,只影响光照。如果定义了法线贴图,则将忽略该贴图。
// bumpScale : Float 凹凸贴图会对材质产生多大影响。典型范围是0-1。默认值为1。
const texture = textureLoader.load("./textures/stone/stone.jpg");
meshs = addGeometrys([texture]);
meshs[2].material.bumpMap = textureLoader.load("./textures/stone/stone-bump.jpg"); //凸凹贴图
meshs[2].material.bumpScale = 1;
};
this.loadNormalmap = function () {
for (let i in meshs) {
scene.remove(meshs[i]);
}
// 用于创建法线贴图的纹理。RGB值会影响每个像素片段的曲面法线,并更改颜色照亮的方式。
// 法线贴图不会改变曲面的实际形状,只会改变光照。
// normalScale : Vector2 法线贴图对材质的影响程度。典型范围是0-1。默认值是Vector2设置为(1,1)
const texture = textureLoader.load("./textures/general/plaster.jpg");
meshs = addGeometrys([texture]);
meshs[2].material.normalMap = textureLoader.load("./textures/general/plaster-normal.jpg"); //法线贴图
};
this.loadDisplacementMap = function () {
for (let i in meshs) {
scene.remove(meshs[i]);
}
// 位移贴图会影响网格顶点的位置,与仅影响材质的光照和阴影的其他贴图不同,移位的顶点可以投射阴影,阻挡其他对象,以及充当真实的几何体。
// 位移纹理是指:网格的所有顶点被映射为图像中每个像素的值(白色是最高的),并且被重定位。
// displacementScale : Float 位移贴图对网格的影响程度(黑色是无位移,白色是最大位移)。如果没有设置位移贴图,则不会应用此值。默认值为1。
// displacementBias : Float 位移贴图在网格顶点上的偏移量。如果没有设置位移贴图,则不会应用此值。默认值为0。
const texture = textureLoader.load("./textures/w_c.jpg");
meshs = addGeometrys([texture]);
meshs[1].material.displacementMap = textureLoader.load("./textures/w_d.png"); //位移贴图
};
this.loadAoMap = function () {
for (let i in meshs) {
scene.remove(meshs[i]);
}
// aoMap : Texture 该纹理的红色通道用作环境遮挡贴图。默认值为null。aoMap需要第二组UV。
// aoMapIntensity : Float 环境遮挡效果的强度。默认值为1。零是不遮挡效果。
meshs = addGeometrys([]);
meshs[2].material.aoMap = textureLoader.load("./textures/ambient.png");
meshs[2].material.aoMapIntensity = 1;
};
this.loadLightMap = function () {
for (let i in meshs) {
scene.remove(meshs[i]);
}
// lightMap : Texture 光照贴图。默认值为null。lightMap需要第二组UV。
// lightMapIntensity : Float 烘焙光的强度。默认值为1。
meshs = addGeometrys([]);
meshs[2].material.lightMap = textureLoader.load("./textures/lightmap/lightmap.png");
};
this.loadMetalRoughnessMap = function () {
for (let i in meshs) {
scene.remove(meshs[i]);
}
scene.remove(groundPlane);
const urls = [
"./textures/cubemap/colloseum/right.png",
"./textures/cubemap/colloseum/left.png",
"./textures/cubemap/colloseum/top.png",
"./textures/cubemap/colloseum/bottom.png",
"./textures/cubemap/colloseum/front.png",
"./textures/cubemap/colloseum/back.png",
];
const cubeLoader = new THREE.CubeTextureLoader();
//背景
scene.background = cubeLoader.load(urls);
meshs = addGeometrys([]);
// metalnessMap : Texture 该纹理的蓝色通道用于改变材质的金属度。
meshs[0].material.metalnessMap = textureLoader.load("./textures/engraved/roughness-map.jpg");
// roughnessMap : Texture 该纹理的绿色通道用于改变材质的粗糙度。
meshs[2].material.roughnessMap = textureLoader.load("./textures/engraved/roughness-map.jpg");
};
this.loadAlphaMap = function () {
for (let i in meshs) {
scene.remove(meshs[i]);
}
// alphaMap: Texture alpha贴图是一张灰度纹理,用于控制整个表面的不透明度。(黑色:完全透明;白色:完全不透明)
// alphaTest: Float 设置运行alphaTest时要使用的alpha值。如果不透明度低于此值,则不会渲染材质。默认值为0。
meshs = addGeometrys([]);
meshs[0].material.alphaMap = textureLoader.load("./textures/alpha/partial-transparency.png");
meshs[0].material.alphaTest = 0.5;
};
this.loadEmissiveMap = function () {
for (let i in meshs) {
scene.remove(meshs[i]);
}
// emissive : Color 材质的放射(光)颜色,基本上是不受其他光照影响的固有颜色。默认为黑色。
// emissiveMap : Texture 设置放射(发光)贴图。默认值为null。放射贴图颜色由放射颜色和强度所调节。 如果你有一个放射贴图,请务必将放射颜色设置为黑色以外的其他颜色。
// emissiveIntensity : Float 放射光强度。调节发光颜色。默认为1。
const material = new THREE.MeshStandardMaterial({
emissive: 0xffffff,
emissiveMap: textureLoader.load("./textures/emissive/lava.png"),
normalMap: textureLoader.load("./textures/emissive/lava-normals.png"),
metalnessMap: textureLoader.load("./textures/emissive/lava-smoothness.png"),
metalness: 1,
roughness: 0.4,
normalScale: new THREE.Vector2(4, 4),
});
meshs = addGeometrys([]);
meshs[0].material = material;
meshs[1].material = material;
};
this.loadSpecularMap = function () {
for (let i in meshs) {
scene.remove(meshs[i]);
}
// specularMap : Texture 镜面反射贴图值会影响镜面高光以及环境贴图对表面的影响程度。默认值为null。
const material = new THREE.MeshPhongMaterial({
map: textureLoader.load("./textures/earth/Earth.png"),
normalMap: textureLoader.load("./textures/earth/EarthNormal.png"),
specularMap: textureLoader.load("./textures/earth/EarthSpec.png"),
normalScale: new THREE.Vector2(6, 6),
});
meshs = addGeometrys([]);
meshs[0].material = material;
meshs[1].material = material;
};
})();
gui.add(spotLight, "intensity", 0, 30, 1).name("聚光源强度");
gui.add(controls, "clearScene");
gui.add(controls, "loadDds");
gui.add(controls, "loadPvr");
gui.add(controls, "loadTga");
gui.add(controls, "loadKtx");
gui.add(controls, "loadExr");
gui.add(controls, "loadRgbe");
const obj = {
bumpScale: 1,
normalScaleX: 1,
normalScaleY: 1,
displacementScale: 1,
displacementBias: 0,
aoMapIntensity: 1,
lightMapIntensity: 1,
emissiveIntensity: 1,
};
const gui_map = gui.addFolder("map");
gui_map.add(controls, "loadBumpmap");
gui_map.add(obj, "bumpScale", 0, 1).onChange(function (e) {
meshs[2].material.bumpScale = e;
});
gui_map.add(controls, "loadNormalmap");
gui_map.add(obj, "normalScaleX", -3, 3).onChange(function (e) {
meshs[2].material.normalScale.set(obj.normalScaleX, obj.normalScaleY);
});
gui_map.add(obj, "normalScaleY", -3, 3).onChange(function (e) {
meshs[2].material.normalScale.set(obj.normalScaleX, obj.normalScaleY);
});
gui_map.add(controls, "loadDisplacementMap");
gui_map.add(obj, "displacementScale", -5, 5).onChange(function (e) {
meshs[1].material.displacementScale = e;
});
gui_map.add(obj, "displacementBias", -5, 5).onChange(function (e) {
meshs[1].material.displacementBias = e;
});
gui_map.add(controls, "loadAoMap");
gui_map.add(obj, "aoMapIntensity", 0, 5).onChange(function (e) {
meshs[2].material.aoMapIntensity = e;
});
gui_map.add(controls, "loadLightMap");
gui_map.add(obj, "lightMapIntensity", 0, 5).onChange(function (e) {
meshs[2].material.lightMapIntensity = e;
});
gui_map.add(controls, "loadMetalRoughnessMap");
gui_map.add(controls, "loadAlphaMap");
gui_map.add(controls, "loadEmissiveMap");
gui_map.add(obj, "emissiveIntensity", 0, 5, 0.5).onChange(function (e) {
meshs[0].material.emissiveIntensity = e;
});
gui_map.add(controls, "loadSpecularMap");
return controls;
}
function determineFormat() {
if (renderer.extensions.get("WEBGL_compressed_texture_astc") !== null) return "astc";
if (renderer.extensions.get("WEBGL_compressed_texture_etc1") !== null) return "etc1";
if (renderer.extensions.get("WEBGL_compressed_texture_s3tc") !== null) return "s3tc";
if (renderer.extensions.get("WEBGL_compressed_texture_pvrtc") !== null) return "pvrtc";
}
}
init();
</script>
合集:
three.js基础
分类:
javascript
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix