效果图:实际效果,图中的贴图是可以动的
一、准备工作
1、静态文件
2、首先你要引入相关依赖:
threejs核心依赖: http://www.yanhuangxueyuan.com/versions/threejsR92/build/three.min.js
兼容检测器: http://www.yanhuangxueyuan.com/versions/threejsR92/build/three.min.js
运行帧数监测器: http://www.yanhuangxueyuan.com/versions/threejsR92/examples/js/libs/stats.min.js
轨道控制器: http://www.yanhuangxueyuan.com/versions/threejsR92/examples/js/libs/stats.min.js
3、 接下来从Vue项目中的运用来说, 以上依赖库,可以在 public/index.html
中引入,也可以下载到项目本地,然后再main.js
中import引入
二、下面开始编写代码
- 首先你需要在页面中准备好一个DOM容器, 如下
<div id="ThreeJS"></div>
- 创建变量
data() {
return {
scene: null, // 场景对象
camera: null, // 相机对象
renderer: null, // 渲染对象
controls: null, // 轨道控制器
stats: null // 运行帧数监测器
}
}
- 调用时需要在页面DOM挂载完成时再调用
mounted() {
this.init()
}
- 功能函数
methods: {
init() {
// 设置全局变量,这些变量你可以写在这里,当然也可以写在 data 函数中
var scene, renderer, camera, annie, boomer;
// 创建时钟
var clock = new THREE.Clock();
// 获取渲染容器
var container = document.getElementById("ThreeJS");
// 场景设置
scene = new THREE.Scene();
// 相机设置
var SCREEN_WIDTH = window.innerWidth,
SCREEN_HEIGHT = window.innerHeight;
var VIEW_ANGLE = 45,
ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT,
NEAR = 0.1,
FAR = 20000;
camera = new THREE.PerspectiveCamera(
VIEW_ANGLE,
ASPECT,
NEAR,
FAR
);
// 添加相机到场景
scene.add(camera);
// 相机位置定位
camera.position.set(0, 150, 400);
// 设置相机照向的位置为: scene.position(场景的方向)
camera.lookAt(scene.position);
// 兼容类型监测
if (!Detector.webgl) return alert('不支持')
renderer = new THREE.WebGLRenderer({
antialias: true,
})
renderer = new THREE.CanvasRenderer();
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
container.appendChild(renderer.domElement);
// 轨道控制器
controls = new THREE.OrbitControls(
camera,
renderer.domElement
);
// 运行帧数监测器
stats = new Stats();
stats.domElement.style.position = "absolute";
stats.domElement.style.bottom = "0px";
stats.domElement.style.zIndex = 100;
container.appendChild(stats.domElement);
// 设置灯光
var light = new THREE.PointLight(0xffffff);
light.position.set(0, 250, 0);
scene.add(light);
// 地平面纹理贴图
var floorTexture = new THREE.ImageUtils.loadTexture(
"images/checkerboard.jpg"
);
// 设置阵列模式为: THREE.RepeatWrapping
floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
floorTexture.repeat.set(10, 10);
var floorMaterial = new THREE.MeshBasicMaterial({
map: floorTexture,
side: THREE.DoubleSide,
});
var floorGeometry = new THREE.PlaneGeometry(1000, 1000, 10, 10);
var floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.position.y = -0.5;
floor.rotation.x = Math.PI / 2;
scene.add(floor);
// SKYBOX/FOG
var skyBoxGeometry = new THREE.CubeGeometry(10000, 10000, 10000);
var skyBoxMaterial = new THREE.MeshBasicMaterial({
color: 0x9999ff,
side: THREE.BackSide,
});
var skyBox = new THREE.Mesh(skyBoxGeometry, skyBoxMaterial);
// scene.add(skyBox);
scene.fog = new THREE.FogExp2(0x9999ff, 0.00025);
// 网格与纹理动画
var runnerTexture = new THREE.ImageUtils.loadTexture(
"images/run.png"
);
// 参数说明:材质, 水平排列, 垂直平铺, 图片中有几个动作, 持续时间.
annie = new TextureAnimator(runnerTexture, 10, 1, 10, 75);
var runnerMaterial = new THREE.MeshBasicMaterial({
map: runnerTexture,
side: THREE.DoubleSide,
});
var runnerGeometry = new THREE.PlaneGeometry(50, 50, 1, 1);
var runner = new THREE.Mesh(runnerGeometry, runnerMaterial);
runner.position.set(-100, 25, 0);
scene.add(runner);
var explosionTexture = new THREE.ImageUtils.loadTexture(
"images/explosion.jpg"
);
// 参数说明:材质, 水平排列, 垂直平铺, 图片中有几个动作, 持续时间.
boomer = new TextureAnimator(explosionTexture, 4, 4, 16, 55);
var explosionMaterial = new THREE.MeshBasicMaterial({
map: explosionTexture,
});
var cubeGeometry = new THREE.CubeGeometry(50, 50, 50);
var cube = new THREE.Mesh(cubeGeometry, explosionMaterial);
cube.position.set(0, 26, 0);
scene.add(cube);
// 纹理更新函数
function update() {
var delta = clock.getDelta();
annie.update(1000 * delta);
boomer.update(1000 * delta);
controls.update();
stats.update();
}
// 渲染函数
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
update();
}
animate();
// 关键代码,实现纹理动画的函数
function TextureAnimator(
texture,
tilesHoriz,
tilesVert,
numTiles,
tileDispDuration
) {
var tilesHorizontal = tilesHoriz;
var tilesVertical = tilesVert;
var numberOfTiles = numTiles;
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set(1 / tilesHorizontal, 1 / tilesVertical);
var tileDisplayDuration = tileDispDuration;
var currentDisplayTime = 0;
var currentTile = 0;
this.update = function (milliSec) {
currentDisplayTime += milliSec;
while (currentDisplayTime > tileDisplayDuration) {
currentDisplayTime -= tileDisplayDuration;
currentTile++;
if (currentTile == numberOfTiles) currentTile = 0;
var currentColumn = currentTile % tilesHorizontal;
texture.offset.x = currentColumn / tilesHorizontal;
var currentRow = Math.floor(currentTile / tilesHorizontal);
texture.offset.y = currentRow / tilesVertical;
}
};
}
}
}
穿插:
由上面的实际效果观看,似乎并看不出什么问题,但是我们的场景是可以随意旋转的,这时就回出现一个问题,因为贴图在一个方向上渲染,当场景旋转至某一个特定角度时,就回出现看不见贴图的现象
而针对这个问题怎么解决的?请看我的另一篇博文
点击这里去查看问题的解决方法:https://blog.csdn.net/bigpatten/article/details/124843012
注:以上就是相关代码,如有疑问请在下方留言,博主会及时回复!!!