11.SphereGeometry球体与球体属性控制
<!DOCTYPE html>
<html>
<head>
<title>threejs</title>
<meta charset="UTF-8" />
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="webgl-output">
</div>
<div id="myStats"></div>
<script type="module">
import * as THREE from "../../libs/build/three.module.js"
import { dat } from "../../libs/dat.gui/dat.gui.js"
import { GLTFLoader } from "../../libs/three.js/jsm/loaders/GLTFLoader.js"
import { OrbitControls } from "../../libs/three.js/jsm/controls/OrbitControls.js"
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
var render = new THREE.WebGLRenderer();
render.setClearColor(new THREE.Color(0x000000));
render.setSize(window.innerWidth, window.innerHeight);
render.shadowMap.enabled = true;
document.getElementById("webgl-output").appendChild(render.domElement);
var axes = new THREE.AxesHelper(50);
scene.add(axes);
//loadModel();
var planeGeometry = new THREE.PlaneGeometry(100, 100);
var planeMaterial = new THREE.MeshLambertMaterial({ color: 0xAAAAAA });
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = -0.5 * Math.PI;
plane.position.set(15, 0, 0);
plane.receiveShadow = true;
//scene.add(plane);
camera.position.x = -5;
camera.position.y = 5;
camera.position.z = 5;
camera.lookAt(scene.position);
scene.add(camera);
var spotLight = new THREE.SpotLight(0xFFFFFF);
spotLight.position.set(-60, 30, -65);
spotLight.castShadow = true;
spotLight.shadow.mapSize = new THREE.Vector2(1024, 1024);
spotLight.shadow.camera.far = 130;
spotLight.shadow.camera.near = 40;
// scene.add(spotLight);
var ambienLight = new THREE.AmbientLight(0xcccccc);
// scene.add(ambienLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 2);
directionalLight.castShadow = true;
directionalLight.shadow.mapSize.width = 2048;
directionalLight.shadow.mapSize.height = 2048;
directionalLight.position.set(20, 20, 20);
scene.add(directionalLight);
//下面介绍SphereGeometry球体,其非常灵活,可以用来创建所有和球体相关的集合
//它有7个构造参数,第一个表示球体半径默认为1,第二个构造参数表示水平分段数默认为32最小为3,第三个表示垂直分段数默认值为16最小为2
//第四个表示水平起始角度默认值为0,第五个表示水平扫描角度的大小默认值为2π,第六个表示垂直起始角度,默认值为0,第七个构造参数表示垂直扫描角度大小默认为π
//看文字很难理解 我们还是用dat.GUI库来测试方便理解,同时让图形的wireframe属性为真,让图形渲染成线框更方便我理解
var sphereGeo = new THREE.SphereGeometry();
var sphereMat = new THREE.MeshBasicMaterial({ color: 0xffffff, wireframe: true });
var sphere = new THREE.Mesh(sphereGeo, sphereMat);
scene.add(sphere);
var ctrlObj = {//稳了更好的了解点球的属性,我们依然和之前一样通过dat.GUI来进行属性的控制
radius: 3,
widthSegments: 32,
heightSegments: 16,
phiStart: 0,
phiLength: Math.PI * 2.0,
thetaStart: 0,
thetaLength: Math.PI,
};
var ctrl = new dat.GUI();//创建dat.GUI对象
var sphereFolder = ctrl.addFolder("sphere");//通过该对象创建一个分组
//这里注意不能直接修改球体的半径!!!需要在回调函数中删除原来的图形,再新建一个修改参数后的平面并添加到场景中就可以了!
sphereFolder.add(ctrlObj, "radius", 1, 100).onChange(function (e) {
scene.remove(sphere);
sphereGeo = new THREE.SphereGeometry(ctrlObj.radius, ctrlObj.widthSegments, ctrlObj.heightSegments, ctrlObj.phiStart, ctrlObj.phiLength, ctrlObj.thetaStart, ctrlObj.thetaLength);
sphere = new THREE.Mesh(sphereGeo, sphereMat);
scene.add(sphere);
});
sphereFolder.add(ctrlObj, "widthSegments", 3, 100).onChange(function (e) {
scene.remove(sphere);
sphereGeo = new THREE.SphereGeometry(ctrlObj.radius, ctrlObj.widthSegments, ctrlObj.heightSegments, ctrlObj.phiStart, ctrlObj.phiLength, ctrlObj.thetaStart, ctrlObj.thetaLength);
sphere = new THREE.Mesh(sphereGeo, sphereMat);
scene.add(sphere);
});
sphereFolder.add(ctrlObj, "heightSegments", 2, 100).onChange(function (e) {
scene.remove(sphere);
sphereGeo = new THREE.SphereGeometry(ctrlObj.radius, ctrlObj.widthSegments, ctrlObj.heightSegments, ctrlObj.phiStart, ctrlObj.phiLength, ctrlObj.thetaStart, ctrlObj.thetaLength);
sphere = new THREE.Mesh(sphereGeo, sphereMat);
scene.add(sphere);
});
sphereFolder.add(ctrlObj, "phiStart", 0, Math.PI * 2.0).onChange(function (e) {
scene.remove(sphere);
sphereGeo = new THREE.SphereGeometry(ctrlObj.radius, ctrlObj.widthSegments, ctrlObj.heightSegments, ctrlObj.phiStart, ctrlObj.phiLength, ctrlObj.thetaStart, ctrlObj.thetaLength);
sphere = new THREE.Mesh(sphereGeo, sphereMat);
scene.add(sphere);
});
sphereFolder.add(ctrlObj, "phiLength", 0, Math.PI * 2.0).onChange(function (e) {
scene.remove(sphere);
sphereGeo = new THREE.SphereGeometry(ctrlObj.radius, ctrlObj.widthSegments, ctrlObj.heightSegments, ctrlObj.phiStart, ctrlObj.phiLength, ctrlObj.thetaStart, ctrlObj.thetaLength);
sphere = new THREE.Mesh(sphereGeo, sphereMat);
scene.add(sphere);
});
sphereFolder.add(ctrlObj, "thetaStart", 0, Math.PI).onChange(function (e) {
scene.remove(sphere);
sphereGeo = new THREE.SphereGeometry(ctrlObj.radius, ctrlObj.widthSegments, ctrlObj.heightSegments, ctrlObj.phiStart, ctrlObj.phiLength, ctrlObj.thetaStart, ctrlObj.thetaLength);
sphere = new THREE.Mesh(sphereGeo, sphereMat);
scene.add(sphere);
});
sphereFolder.add(ctrlObj, "thetaLength", 0, Math.PI).onChange(function (e) {
scene.remove(sphere);
sphereGeo = new THREE.SphereGeometry(ctrlObj.radius, ctrlObj.widthSegments, ctrlObj.heightSegments, ctrlObj.phiStart, ctrlObj.phiLength, ctrlObj.thetaStart, ctrlObj.thetaLength);
sphere = new THREE.Mesh(sphereGeo, sphereMat);
scene.add(sphere);
});
var controls = new OrbitControls(camera, render.domElement);
controls.update();
renderScene();
function renderScene() {
controls.update();
requestAnimationFrame(renderScene);
render.render(scene, camera);
}
window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
render.setSize(window.innerWidth, window.innerHeight);
}
function loadModel() {
new GLTFLoader().setPath("model/")
.load("untitled.glb", function (gltf) {
gltf.scene.scale.set(0.01, 0.01, 0.01);
gltf.scene.traverse(function (object) {
if (object.isMesh)
object.castShadow = true;
});
scene.add(gltf.scene);
})
}
</script>
</body>
</html>
12.ConvexGeometry凸面几何体
<!DOCTYPE html>
<html>
<head>
<title>threejs</title>
<meta charset="UTF-8" />
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="webgl-output">
</div>
<div id="myStats"></div>
<script type="module">
import * as THREE from "../../libs/build/three.module.js"
import { dat } from "../../libs/dat.gui/dat.gui.js"
import { Stats } from "../../libs/Stats/Stats.js"
import { GLTFLoader } from "../../libs/three.js/jsm/loaders/GLTFLoader.js"
import { OrbitControls } from "../../libs/three.js/jsm/controls/OrbitControls.js"
//导入ConvexGeometry
import { ConvexGeometry } from "../../libs/three.js/jsm/geometries/ConvexGeometry.js"
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
var render = new THREE.WebGLRenderer();
render.setClearColor(new THREE.Color(0x000000));
render.setSize(window.innerWidth, window.innerHeight);
render.shadowMap.enabled = true;
document.getElementById("webgl-output").appendChild(render.domElement);
var axes = new THREE.AxesHelper(500);
scene.add(axes);
//loadModel();
var planeGeometry = new THREE.PlaneGeometry(100, 100);
var planeMaterial = new THREE.MeshLambertMaterial({ color: 0xAAAAAA });
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = -0.5 * Math.PI;
plane.position.set(15, 0, 0);
plane.receiveShadow = true;
//scene.add(plane);
camera.position.x = -5;
camera.position.y = 5;
camera.position.z = 5;
camera.lookAt(scene.position);
scene.add(camera);
var ambienLight = new THREE.AmbientLight(0xcccccc);
// scene.add(ambienLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 2);
directionalLight.castShadow = true;
directionalLight.shadow.mapSize.width = 2048;
directionalLight.shadow.mapSize.height = 2048;
directionalLight.position.set(20, 20, 20);
scene.add(directionalLight);
//学习一下ConvexGeometry凸面几何体,threejs标准库里没有包含这种高级几何体,我们需要import他们
//通过ConvexGeometry,我们可以围绕一组点创建一个凸包,所谓凸包,就是包围这组点的最小图形,那么我们先要创建一组点
var convexPoints = [];
for (var i = 0; i < 20; i++) {//写个20次的循环,每次生成三个范围-20到20的随机数
var x = Math.random() * 40 - 20;
var y = Math.random() * 40 - 20;
var z = Math.random() * 40 - 20;
convexPoints.push(new THREE.Vector3(x, y, z));//并组成三维坐标放入点的数组中
};//为了能够直接看到这些点的位置,我们需要遍历数组,在每个点的位置创建一个红色的球体
convexPoints.forEach(function (convexPoint) {
var convexSphereGeo = new THREE.SphereGeometry(0.3);
var convexSphereMat = new THREE.MeshBasicMaterial({ color: 0xff0000 });
var convexSphere = new THREE.Mesh(convexSphereGeo, convexSphereMat);
convexSphere.position.copy(convexPoint);//位置对应点的位置
scene.add(convexSphere);//把每个小球都添加到场景中
})
//我们现在创建一个ConvexGeometry凸面几何体,他只有一个构造参数,就是三维坐标数组,我们把刚才创建的数组传入它的构造函数中
var convexGeo = new ConvexGeometry(convexPoints);
var convexMat = new THREE.MeshBasicMaterial({ color: 0x00ff00, wireframe: true });//材质设置为绿色,线框属性设置为真以便观察结构
var convex = new THREE.Mesh(convexGeo, convexMat);
scene.add(convex);//把凸面几何体添加到场景中,刷新一下看看效果
//因为我们用的是随机的坐标,所以每次刷新生成的凸面几何体都不一样
var controls = new OrbitControls(camera, render.domElement);
controls.update();
var stats = addStats();
renderScene();
function renderScene() {
controls.update();
stats.update();
requestAnimationFrame(renderScene);
render.render(scene, camera);
}
window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
render.setSize(window.innerWidth, window.innerHeight);
}
function addStats() {
var stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
stats.setMode(0);
document.getElementById("myStats").appendChild(stats.domElement);
return stats;
}
</script>
</body>
</html>
13.学习一下如何通过空间中的点构造曲线路径
//学习一下如何通过空间中的点构造曲线路径
var Points = [];//新建一组点构成路径
for (var i = 0; i < 10; i++) {//
Points.push(new THREE.Vector3(i * 3, Math.sin(i) * 5, i * 3));//组成三维坐标放入点的数组中
};//为了能够直接看到这些点的位置,我们需要遍历数组,在每个点的位置创建一个红色的球体
Points.forEach(function (Point) {
var SphereGeo = new THREE.SphereGeometry(0.2);
var SphereMat = new THREE.MeshBasicMaterial({ color: 0xff0000 });
var Sphere = new THREE.Mesh(SphereGeo, SphereMat);
Sphere.position.copy(Point);//位置对应点的位置
scene.add(Sphere);//把每个小球都添加到场景中
})//刷新一下浏览器发现点已经显示出来了
//接下来我们用这些点创建一个路径,我们可以使用Three.CatmullRomCurve生成一条三维CarmullROM曲线路径
var path = new THREE.CatmullRomCurve3(Points);
var lineGeo = new THREE.BufferGeometry();//为了能够看到路径,我们在路径的位置创建一条曲线,新建一个BufferGeometry(自定义几何体)
lineGeo.setFromPoints(path.getPoints(10));//在使用setFromPoints给它设置坐标,坐标可以用getPoints从路径上获得,getPoints参数表示获得点的数量
var lineMat = new THREE.LineBasicMaterial({ color: 0xff0000 });//线条的颜色设置为红色
var line = new THREE.Line(lineGeo, lineMat);
scene.add(line);//刷新浏览器,可以看到线条已经出线在场景中了
//修改一下getPoints的参数,我们测试发现值越大曲线越平滑,当参数很小,几乎是由点连成的直线,当参数为100,几乎成光滑曲线
14.Material的基本属性和材质贴图方法
<!DOCTYPE html>
<html>
<head>
<title>threejs</title>
<meta charset="UTF-8" />
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="webgl-output">
</div>
<div id="myStats"></div>
<script type="module">
import * as THREE from "../../libs/build/three.module.js"
import { dat } from "../../libs/dat.gui/dat.gui.js"
import { Stats } from "../../libs/Stats/Stats.js"
import { GLTFLoader } from "../../libs/three.js/jsm/loaders/GLTFLoader.js"
import { OrbitControls } from "../../libs/three.js/jsm/controls/OrbitControls.js"
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
var render = new THREE.WebGLRenderer();
render.setClearColor(new THREE.Color(0xffffff));
render.setSize(window.innerWidth, window.innerHeight);
render.shadowMap.enabled = true;
document.getElementById("webgl-output").appendChild(render.domElement);
var axes = new THREE.AxesHelper(500);
scene.add(axes);
//loadModel();
camera.position.x = 50;
camera.position.y = 50;
camera.position.z = 50;
camera.lookAt(scene.position);
scene.add(camera);
var ambienLight = new THREE.AmbientLight(0xcccccc);
// scene.add(ambienLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 2);
directionalLight.castShadow = true;
directionalLight.shadow.mapSize.width = 2048;
directionalLight.shadow.mapSize.height = 2048;
directionalLight.position.set(20, 20, 20);
scene.add(directionalLight);
//本节课我们学习材质的几种属性,这几种属性是所有材质最常用的,所有的材质都有一个共同的基类,Material,今天学习的几个属性便是这个基类中常用的属性
var planeGeometry = new THREE.PlaneGeometry(200, 200, 4, 4);//首先用PlaneGeometry几何体创建一个地板
//材质的构造参数是一个用于定义材质外观的对象,具有一个或多个属性,材质的任何属性都可以从此处传入,包括从Material继承的任何属性,所以本节课对Material中属性讲解都通过MeshBasicMaterial来表达
var planeMaterial = new THREE.MeshBasicMaterial({ color: 0x777777 });
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = -0.5 * Math.PI;//调整一下网格位置
plane.position.y = -20;
scene.add(plane);//场景中有一个对照的地步了,我们再来创建一个几何体对象,用于显示我们的属性效果
var cubeGeom = new THREE.BoxGeometry(15, 15, 15);
var cubeMaterial = new THREE.MeshBasicMaterial({ color: 0x7777ff });
var cubeMesh = new THREE.Mesh(cubeGeom, cubeMaterial);
scene.add(cubeMesh);
//为了更好的学习Material中的属性,我们依旧选择dat.GUI库
var ctrlObj = {
visible: true,//该属性默认为true,表示材质可见
transparent: false,//该属性表示此材质是否透明,设置为true时,可以通过设置材质的opacity属性来控制材质透明程度
opacity: 1,//opacity范围是0到1的浮点数默认为1,0表示完全透明,1表示完全不透明,若transparent未设置为true,则材质保持完全不透明,此值仅影响其颜色
side: "front",//side表示需要渲染哪一面,该值有三个可选,分别是THREE.FrontSide、BackSide、DoubleSide
depthTest: true,//这个属性表示在渲染此材质时是否启用深度测试,默认为true
depthWrite: true,//这个属性表示在渲染此材质时是否对深度缓冲区有影响,默认为true
apphaTest: 1,//该属性表示如果不透明度低于此值,则不会渲染材质
}
var control = new dat.GUI();
const folder = control.addFolder("基础属性");
folder.add(ctrlObj, "visible").onChange(function (e) {
cubeMaterial.visible = e;//材质不同于几何体 可以直接修改
});
folder.add(ctrlObj, "transparent").onChange(function (e) {
cubeMaterial.transparent = e;
});
folder.add(ctrlObj, "opacity", 0, 1).onChange(function (e) {
cubeMaterial.opacity = e;
});
folder.add(ctrlObj, "depthTest").onChange(function (e) {
cubeMaterial.depthTest = e;
});
folder.add(ctrlObj, "depthWrite").onChange(function (e) {
cubeMaterial.depthWrite = e;
});
folder.add(ctrlObj, "apphaTest", 0, 1).onChange(function (e) {
cubeMaterial.apphaTest = e;
});
//这边的side属性,我们需要传入一个数组,来让我们选择side的值
folder.add(ctrlObj, "side", ["front", "back", "double"]).onChange(function (e) {
switch (e) {//然后通过 switch case来对不同的值进行不同的属性赋值
case "front":
cubeMaterial.side = THREE.FrontSide;
break;
case "back":
cubeMaterial.side = THREE.BackSide;
break;
case "double":
cubeMaterial.side = THREE.DoubleSide;
break;
default:
break;
}
//cubeMaterial.needsUpdate = true;//然后我们可以在此回调函数中对此材质进行重新编译
});
//为了让这些属性的效果看起来更清楚,我们可以为该正方体材质添加贴图
const textureLoader = new THREE.TextureLoader();//先创建一个TextureLoader对象用于对贴图的加载
const bricks = textureLoader.load("./textures/1.jpg");//然后通过该对象的load方法将指定路径的贴图加载到变量中
cubeMaterial.map = bricks;//再将加载好的贴图设置给材质的map贴图属性
//刷新浏览器可发现我们的贴图已经应用到正方体上了
var controls = new OrbitControls(camera, render.domElement);
controls.update();
var stats = addStats();
renderScene();
function renderScene() {
controls.update();
stats.update();
requestAnimationFrame(renderScene);
render.render(scene, camera);
}
window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
render.setSize(window.innerWidth, window.innerHeight);
}
function addStats() {
var stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
stats.setMode(0);
document.getElementById("myStats").appendChild(stats.domElement);
return stats;
}
</script>
</body>
</html>
15.MeshBasicMaterial的基本属性以及环境贴图和灰度纹理贴图
<!DOCTYPE html>
<html>
<head>
<title>threejs</title>
<meta charset="UTF-8" />
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="webgl-output">
</div>
<div id="myStats"></div>
<script type="module">
import * as THREE from "../../libs/build/three.module.js"
import { dat } from "../../libs/dat.gui/dat.gui.js"
import { Stats } from "../../libs/Stats/Stats.js"
import { GLTFLoader } from "../../libs/three.js/jsm/loaders/GLTFLoader.js"
import { OrbitControls } from "../../libs/three.js/jsm/controls/OrbitControls.js"
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
var render = new THREE.WebGLRenderer();
render.setClearColor(new THREE.Color(0xffffff));
render.setSize(window.innerWidth, window.innerHeight);
render.shadowMap.enabled = true;
document.getElementById("webgl-output").appendChild(render.domElement);
var axes = new THREE.AxesHelper(500);
scene.add(axes);
//loadModel();
camera.position.set(30, 30, 30);//调整一下相机位置
camera.lookAt(scene.position);
scene.add(camera);
var ambienLight = new THREE.AmbientLight(0xcccccc);
// scene.add(ambienLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 2);
directionalLight.castShadow = true;
directionalLight.shadow.mapSize.width = 2048;
directionalLight.shadow.mapSize.height = 2048;
directionalLight.position.set(20, 20, 20);
scene.add(directionalLight);
//本节课我们沿用上节课案例来学习本节课的MeshBasicMaterial基础网格材质,这是一种非常简单的材质,不需要考虑场景中光照的影响,使用这种材质的网格会被渲染成简单的平面多边形,也可以显示几何体线框
var planeGeometry = new THREE.PlaneGeometry(200, 200, 4, 4);
var planeMaterial = new THREE.MeshBasicMaterial({ color: 0x777777 });
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = -0.5 * Math.PI;
plane.position.y = -20;
scene.add(plane);
var cubeGeom = new THREE.BoxGeometry(15, 15, 15);
var cubeMaterial = new THREE.MeshBasicMaterial({ color: 0x7777ff });
var cubeMesh = new THREE.Mesh(cubeGeom, cubeMaterial);
scene.add(cubeMesh);
var ctrlObj = {
visible: true,
transparent: false,
opacity: 1,
side: "front",
depthTest: true,
depthWrite: true,
apphaTest: 1,//我们将学习的属性保存在上节课对象中
color: 0x7777ff,//材质颜色默认白色
wireframe: false,//线框属性,该属性能将几何体渲染成线框,默认值false
map: true,//为了能够将后面的效果显示更加清楚,我们需要定义一个map属性,该属性设置材质中map颜色贴图是否存在
reflectivity: 1,//该属性表示环境贴图对表面的影响程度,默认为1,范围0到1,0表示无反射,1表示完全反射
refractionRatio: 0.98,//该属性表示空气的折射率除以材质的折射率,默认0.98
combine: "Multiply",//该属性表示如何将表面颜色的结果与环境贴图结合起来,默认MultiplyOperation,可选值MixOperation和AddOperation
alphaMap: true,表示该图形是否存在灰度纹理,用于控制整个表面的不透明度
}
var control = new dat.GUI();
const folder = control.addFolder("基础属性");
folder.add(ctrlObj, "visible").onChange(function (e) {
cubeMaterial.visible = e;
});
folder.add(ctrlObj, "transparent").onChange(function (e) {
cubeMaterial.transparent = e;
});
folder.add(ctrlObj, "opacity", 0, 1).onChange(function (e) {
cubeMaterial.opacity = e;
});
folder.add(ctrlObj, "depthTest").onChange(function (e) {
cubeMaterial.depthTest = e;
});
folder.add(ctrlObj, "depthWrite").onChange(function (e) {
cubeMaterial.depthWrite = e;
});
folder.add(ctrlObj, "apphaTest", 0, 1).onChange(function (e) {
cubeMaterial.apphaTest = e;
});
folder.add(ctrlObj, "side", ["front", "back", "double"]).onChange(function (e) {
switch (e) {
case "front":
cubeMaterial.side = THREE.FrontSide;
break;
case "back":
cubeMaterial.side = THREE.BackSide;
break;
case "double":
cubeMaterial.side = THREE.DoubleSide;
break;
default:
break;
}
cubeMaterial.needsUpdate = true;
});
const textureLoader = new THREE.TextureLoader();
const bricks = textureLoader.load("./textures/1.jpg");
cubeMaterial.map = bricks;
const Basicfolder = control.addFolder("MeshBasicMaterial");//再来为这次学习的MeshBasicMaterial材质属性,创建一个分组,我们会将今天学习的几种属性添加到该分组里
Basicfolder.addColor(ctrlObj, "color").onChange(function (e) {
cubeMaterial.color = new THREE.Color(e);
});//添加完成后,刷新浏览器,调整颜色值,可以发现材质的颜色和颜色贴图的效果进行了混合
Basicfolder.add(ctrlObj, "wireframe").onChange(function (e) {
cubeMaterial.wireframe = e;
});//添加后我们设置wireframe为true,正方体渲染成了线框,这种效果非常适用于调试
Basicfolder.add(ctrlObj, "map").onChange(function (e) {//当值为真时,我们将颜色贴图设置为对应纹理否则不设置颜色贴图
cubeMaterial.map = e ? bricks : null;
cubeMaterial.needsUpdate = true;//设置完成后我们需要使用基类中的needsUpdate属性来重新编译材质
});
Basicfolder.add(ctrlObj, "reflectivity", 0, 1).onChange(function (e) {
cubeMaterial.reflectivity = e;
});//正方体没有任何变化 是因为我们没有设置环境贴图,因此我们需要将对应贴图加载到项目中,我们在下面封装一个加载环境贴图的方法,并在下面调用这个方法给正方体设置环境贴图
//在给正方形设置环境贴图之后,我们在控制菜单将正方体的颜色贴图去除,可以清晰的看到环境贴图效果,再来对reflectivity进行修改,可以看到正方体的变化
var textureCube = creatEnv();//在这里调用加载环境贴图的方法,将返回出来的纹理放到一个变量中
cubeMaterial.envMap = textureCube;//给正方形设置环境贴图
Basicfolder.add(ctrlObj, "refractionRatio", 0, 1).onChange(function (e) {
cubeMaterial.refractionRatio = e;
});//修改refractionRatio,可以看到正方体反射的场景距离发生变化
Basicfolder.add(ctrlObj, "combine", ["Multiply", "Mix", "Add"]).onChange(function (e) {
switch (e) {
case "Multiply":
cubeMaterial.combine = THREE.MultiplyOperation;
break;
case "Mix":
cubeMaterial.combine = THREE.MixOperation;
break;
case "Add":
cubeMaterial.combine = THREE.AddOperation;
break;
default:
break;
}
cubeMaterial.needsUpdate = true;
});
const alphaMapTx = textureLoader.load("./textures/2.jpg");//现在我们加载一张纹理贴图
cubeMaterial.alphaMap = alphaMapTx;//为MeshBasicMaterial设置alphaMap属性,该属性表示alpha贴图是一张灰度纹理,用于控制整个表面的不透明度
Basicfolder.add(ctrlObj, "alphaMap").onChange(function (e) {//当值为真时,我们将该灰度纹理贴图设置为对应纹理否则不设置灰度纹理贴图
cubeMaterial.alphaMap = e ? alphaMapTx : null;
cubeMaterial.needsUpdate = true;//设置完成后我们需要使用基类中的needsUpdate属性来重新编译材质
});//刷新浏览器,将transparent设置为真,该纹理贴图显示了
var controls = new OrbitControls(camera, render.domElement);
controls.update();
var stats = addStats();
renderScene();
function renderScene() {
controls.update();
stats.update();
requestAnimationFrame(renderScene);
render.render(scene, camera);
}
window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
render.setSize(window.innerWidth, window.innerHeight);
}
function addStats() {
var stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
stats.setMode(0);
document.getElementById("myStats").appendChild(stats.domElement);
return stats;
}
//环境贴图也叫反射贴图,可以在几何体上反射周围环境,实现模型表面对周围环境的反射效果
function creatEnv() {//加载环境贴图,首先我们需要创建一个数组用于存放环境贴图的路径
//该数组长度为6,分别用于正方体的每一侧,
var path = "./textures/";
var format = '.jpg';
var urls = [//这里图方便用一张图了
path + '4' + format, path + '4' + format,
path + '4' + format, path + '4' + format,
path + '4' + format, path + '4' + format
];
const cubeTxLoader = new THREE.CubeTextureLoader();//再新建一个CubeTextureLoader加载器对象
const refCube = cubeTxLoader.load(urls);//然后通过创建的加载器对象将我们的所有贴图加载到一个变量中
refCube.mapping = THREE.CubeRefractionMapping;//接着再设置纹理贴图的映射模式,此处设置是为了配合后面的refractionRatio属性
refCube.format = THREE.RGBFormat;//接着再设置纹理贴图的格式,对于JPG贴图,我们通常需要设置为RGBFormat格式
return refCube;//最后将我们的贴图返回,以便后续使用
}//这里图片加载容易有错误,环境纹理贴图要求图片长宽相等而其他纹理贴图不需要,不知道是不是因为几何体是正方形的原因
</script>
</body>
</html>
渲染效果图: