[webGL学习]基于three.js构建WebGL实例第六讲
2016-10-13 08:39
555 查看
今天我们继续webGL的课程。 今天我们开始另一个主题,我们将使用sprites和纹理动画。 如果你不知道,sprites只是图像,可以附加到对象上。 这些sprites图像总是与我们的相机正交。 Three.js为sprites - THREE.SpriteMaterial提供了一个库,以及一个特殊的一些方法 - THREE.Sprite。 在本教程中,我们还将学习如何使用sprites播放动画。
创建主要的webGL 场景
首先我们创建一个script.js文件,代码如下var lesson8 = { scene: null, camera: null, renderer: null, container: null, controls: null, clock: null, stats: null, anim1: null, anim2: null, // animations animReady1: false, animReady2: false, init: function() { // initialization // create main scene this.scene = new THREE.Scene(); this.scene.fog = new THREE.FogExp2(0xcce0ff, 0.0003); var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight; // prepare perspective camera var VIEW_ANGLE = 60, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 1, FAR = 1000; this.camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR); this.scene.add(this.camera); this.camera.position.set(100, 0, 0); this.camera.lookAt(new THREE.Vector3(0,0,0)); // prepare webgl renderer this.renderer = new THREE.WebGLRenderer({ antialias:true }); this.renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT); this.renderer.setClearColor(this.scene.fog.color); this.renderer.shadowMapEnabled = true; this.renderer.shadowMapSoft = true; // prepare container this.container = document.createElement('div'); document.body.appendChild(this.container); this.container.appendChild(this.renderer.domElement); // events THREEx.WindowResize(this.renderer, this.camera); // prepare controls (OrbitControls) this.controls = new THREE.OrbitControls(this.camera, this.renderer.domElement); this.controls.target = new THREE.Vector3(0, 0, 0); this.controls.maxDistance = 3000; // prepare clock this.clock = new THREE.Clock(); // prepare stats this.stats = new Stats(); this.stats.domElement.style.position = 'absolute'; this.stats.domElement.style.left = '50px'; this.stats.domElement.style.bottom = '50px'; this.stats.domElement.style.zIndex = 1; this.container.appendChild( this.stats.domElement ); // add lights this.scene.add( new THREE.AmbientLight(0x606060) ); var dirLight = new THREE.DirectionalLight(0xffffff); dirLight.position.set(200, 200, 1000).normalize(); this.camera.add(dirLight); this.camera.add(dirLight.target); // display skybox this.addSkybox(); // display animated objects this.addAnimatedObjects(); }, addSkybox: function() { // define path and box sides images var path = 'skybox/'; var sides = [ path + 'sbox_px.jpg', path + 'sbox_nx.jpg', path + 'sbox_py.jpg', path + 'sbox_ny.jpg', path + 'sbox_pz.jpg', path + 'sbox_nz.jpg' ]; // load images var scCube = THREE.ImageUtils.loadTextureCube(sides); scCube.format = THREE.RGBFormat; // prepare skybox material (shader) var skyShader = THREE.ShaderLib["cube"]; skyShader.uniforms["tCube"].value = scCube; var skyMaterial = new THREE.ShaderMaterial( { fragmentShader: skyShader.fragmentShader, vertexShader: skyShader.vertexShader, uniforms: skyShader.uniforms, depthWrite: false, side: THREE.BackSide }); // create Mesh with cube geometry and add to the scene var skyBox = new THREE.Mesh(new THREE.BoxGeometry(500, 500, 500), skyMaterial); skyMaterial.needsUpdate = true; this.scene.add(skyBox); } }; // animate the scene function animate() { requestAnimationFrame(animate); render(); update(); } // update controls and stats function update() { var delta = lesson8.clock.getDelta(); lesson8.controls.update(delta); lesson8.stats.update(); } // Render the scene function render() { if (lesson8.renderer) { lesson8.renderer.render(lesson8.scene, lesson8.camera); } } // Initialize lesson on page load function initializeLesson() { lesson8.init(); animate(); } if (window.addEventListener) window.addEventListener('load', initializeLesson, false); else if (window.attachEvent) window.attachEvent('onload', initializeLesson); else window.onload = initializeLesson;
这段代码创建了渲染器,摄像头,控制装置,照明,统计数据和天空盒一个基本的场景。类似的代码你已经在前面前面的课程中看到的.
Sprites
如前所述,子画面是与我们的相机正交(垂直)的(二维)图像。 现在让我们使用以下函数将sprites添加到场景中:addAnimatedObjects: function() { var texture1 = new THREE.ImageUtils.loadTexture('images/sprite1.png', undefined, function() { var material1 = new THREE.SpriteMaterial( { map: texture1, useScreenCoordinates: false, side:THREE.DoubleSide, transparent: true } ); var mesh1 = new THREE.Sprite(material1); mesh1.position.set(0, 0, -40); mesh1.scale.set(64, 64, 1.0); lesson8.scene.add(mesh1); }); var texture2 = new THREE.ImageUtils.loadTexture('images/sprite2.png', undefined, function() { var material2 = new THREE.SpriteMaterial( { map: texture2, useScreenCoordinates: false, transparent: true } ); var mesh2 = new THREE.Sprite(material2); mesh2.position.set(0, 0, 40); mesh2.scale.set(24, 46, 1.0); lesson8.scene.add(mesh2); }); }
此代码加载两个图片(sprite1.png和sprite2.png)。 在加载这两个图像之后,我们创建两个sprite材质和Sprite对象,并将它们添加到我们的场景中。 如果现在运行代码,您将在我们的场景中看到两个二维图像。 你可能已经注意到,图像是按照原样绘制 - 我们看到很多小图像(瓷砖) - 这些图像文件被拍摄,因为我们将使用这些瓷砖做动画的事实。
Texture Animation
function TileTextureAnimator(texture, hTiles, vTiles, durationTile) { // current tile number this.currentTile = 0; // duration of every tile this.durationTile = durationTile; // internal time counter this.currentTime = 0; // amount of horizontal and vertical tiles, and total count of tiles this.hTiles = hTiles; this.vTiles = vTiles; this.cntTiles = this.hTiles * this.vTiles; texture.wrapS = texture.wrapT = THREE.RepeatWrapping; texture.repeat.set(1 / this.hTiles, 1 / this.vTiles); this.update = function(time) { this.currentTime += time; while (this.currentTime > this.durationTile) { this.currentTime -= this.durationTile; this.currentTile++; if (this.currentTile == this.cntTiles) { this.currentTile = 0; } var iColumn = this.currentTile % this.hTiles; texture.offset.x = iColumn / this.hTiles; var iRow = Math.floor(this.currentTile / this.hTiles); texture.offset.y = iRow / this.vTiles; } }; }
“TileTextureAnimator”函数调整原始图像以显示动画。 它在从第一个到最后一个图像的图像的图像之间切换。 这是在指定的时间间隔。 每个瓦片在一定的持续时间内可见,在它转向另一个瓦片之后。 现在让我们更新我们之前添加的’addAnimatedObjects’函数:
addAnimatedObjects: function() { var texture1 = new THREE.ImageUtils.loadTexture('images/sprite1.png', undefined, function() { lesson8.anim1 = new TileTextureAnimator(texture1, 8, 8, 100); var material1 = new THREE.SpriteMaterial( { map: texture1, useScreenCoordinates: false, side:THREE.DoubleSide, transparent: true } ); var mesh1 = new THREE.Sprite(material1); mesh1.position.set(0, 0, -40); mesh1.scale.set(64, 64, 1.0); lesson8.scene.add(mesh1); lesson8.animReady1 = true; }); var texture2 = new THREE.ImageUtils.loadTexture('images/sprite2.png', undefined, function() { lesson8.anim2 = new TileTextureAnimator(texture2, 9, 8, 100); var material2 = new THREE.SpriteMaterial( { map: texture2, useScreenCoordinates: false, transparent: true } ); var mesh2 = new THREE.Sprite(material2); mesh2.position.set(0, 0, 40); mesh2.scale.set(24, 46, 1.0); lesson8.scene.add(mesh2); lesson8.animReady2 = true; }); }
第一个sprite图像在行中包含8个图块,总共8个行,第二个图像包含行中的9个图块。 每个图块将可见100ms。 最后,在main’update’函数中,我们需要放置以下代码:
if (lesson8.animReady1) { lesson8.anim1.update(1000 * delta); } if (lesson8.animReady2) { lesson8.anim2.update(1000 * delta); }
结束
未完继续源码下载请关注我的微信公众号
相关文章推荐
- [webGL学习]基于three.js构建WebGL实例第五讲
- [webGL学习]基于three.js构建WebGL实例第二讲
- [webGL学习]基于three.js构建WebGL实例第一讲
- [webGL学习]基于three.js构建WebGL实例第三讲
- [webGL学习]基于three.js构建WebGL实例第一讲
- [webGL学习]基于three.js构建WebGL实例第四讲
- [webGL学习]基于three.js构建WebGL实例讲解大纲
- webgl+three.js,学习笔记,画一个立方体+解析
- 小八——WebGL心路历程(2),一个基于Three.js的webGL程序解析
- webgl+three.js,学习笔记,调用摄像头,做成纹理
- Three.js讲解以及WEBGL实例(转)
- Three.js讲解以及WEBGL实例
- 学习笔记Webgl之Three.js (1)
- Three.JS-学习 The WebGL earth (1)---globe.html 分析
- Three.JS提升学习2:构建Three.js场景的基本组件
- 学习 WebGL 的开源库 Three.js
- WebGL之ThreeJS学习之旅01
- Three.js讲解以及WEBGL实例
- three.js学习笔记 基于物理引擎的第一人称控件
- 20个令人印象深刻的例子学习Three.js实现WebGL