(接上圖)桌上遊戲通常創建於一個核心的實體引擎。因此,要在3D世界中模擬一個柔軟的物體,需要一個完整的實體模擬器,並且建立一個可信的行為。
WebGL和JavaScript還不能奢華到可以運作一個完全成熟的實體模擬器。因此,在這個遊戲中我們必須找到一種方式來創造風的效果。
我們在3D模型中為每個物件嵌入「風敏度」的資訊。 3D模型的每個頂點都有一個“風屬性”,指定頂點應該受到風速多大程度的影響。所以,這指定了3D物體的風敏度。然後,我們需要創建“風”本身。
我們透過建立包含Perlin雜訊的影像來實現。此圖片意在覆蓋一塊確定區域的風。所以,一個考慮它的好方法是,想像3D場景中一個特定矩形區域中像噪音一樣覆蓋一個畫面的雲。這張圖片每個像素的灰階值指定在一個特定的時刻3D區域中風力有多強。
為了創造風的效果,影像以恆定的速率和特定的方向即風的方向移動。並且為了確保「風的區域」不會影響場景中的任何內容,我們將風的影像環繞邊界,限制在效果的區域內。
一個風的簡單3D教學
現在,讓我們透過Three.js在簡單的3D場景創造一個風的效果。
我們將在一個簡單的「程序草」中創造風。
首先,讓我們先建立場景。我們將有一個簡單的、質感平坦的地面。然後每一根草將簡單地用倒立的圓錐體展現。
佈滿小草的地面
下方是如何在Thress.js中用CoffeeScript創造這個簡單的場景。
首先我們要設定Three.js,並把它與相機、滑鼠,以及一些燈光結合在一起:
<br>
constructor: -> @clock = new THREE.Clock() @container = document.createElement( 'p' ); document.body.appendChild( @container ); @renderer = new THREE.WebGLRenderer(); @renderer.setSize( window.innerWidth, window.innerHeight ); @renderer.setClearColorHex( 0x808080, 1 ) @container.appendChild(@renderer.domElement); @camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 5000 ); @camera.position.x = 5; @camera.position.y = 10; @camera.position.z = 40; @controls = new THREE.OrbitControls( @camera, @renderer.domElement ); @controls.enabled = true @scene = new THREE.Scene(); @scene.add( new THREE.AmbientLight 0xFFFFFF ) directional = new THREE.DirectionalLight 0xFFFFFF directional.position.set( 10,10,10) @scene.add( directional ) # Demo data @grassTex = THREE.ImageUtils.loadTexture("textures/grass.png"); @initGrass() @initTerrain() # Stats @stats = new Stats(); @stats.domElement.style.position = 'absolute'; @stats.domElement.style.top = '0px'; @container.appendChild( @stats.domElement ); window.addEventListener( 'resize', @onWindowResize, false ); @animate()
initGrass和initTerrain函數呼叫分別以小草和地面函數呼叫場景:
<br>
initGrass:-> mat = new THREE.MeshPhongMaterial( { map: @grassTex } ) NUM = 15 for i in [0..NUM] by 1 for j in [0..NUM] by 1 x = ((i/NUM) - 0.5) * 50 + THREE.Math.randFloat(-1,1) y = ((j/NUM) - 0.5) * 50 + THREE.Math.randFloat(-1,1) @scene.add( @instanceGrass( x, 2.5, y, 5.0, mat ) ) instanceGrass:(x,y,z,height,mat)-> geometry = new THREE.CylinderGeometry( 0.9, 0.0, height, 3, 5 ) mesh = new THREE.Mesh( geometry, mat ) mesh.position.set( x, y, z ) return mesh
在此我們創造了一個格子,由15*15的小草組成。我們添加了一個隨機數字到每根小草的位置,讓它們不會因為排列的太整齊而有些古怪。
此地形只是水平面,放置在這些小草的根部(Y = 2.5)。
<br>
initTerrain:-> @plane = new THREE.Mesh( new THREE.PlaneGeometry(60, 60, 2, 2), new THREE.MeshPhongMaterial({ map: @grassTex })) @plane.rotation.x = -Math.PI/2 @scene.add( @plane )
所以到目前為止,我們所做的只是簡單地創建了一個Three.js場景,並且添加了一些小草,由程式生成的倒立圓錐創建,以及一個簡單的地面。
目前沒有特別之處。
<br>
現在是增加風的時候了。第一件事,我們希望把風敏度資訊嵌入到草的3D模型中。
我們將這些資訊以自訂屬性嵌入到小草3D模型的每個頂點。我們將要使用的規則是:每個小草模型的底部(圓錐體的頂)所具有的風敏度為0,因為它貼在地面上。小草模型(圓錐體的底部)的頂部具有最大的風敏度,因為它遠離地面。
下方是如何重寫instanceGrass函數來為小草的3D模型增加風敏度作為自訂參數。
<br>
instanceGrass:(x,y,z,height)-> geometry = new THREE.CylinderGeometry( 0.9, 0.0, height, 3, 5 ) for i in [0..geometry.vertices.length-1] by 1 v = geometry.vertices[i] r = (v.y / height) + 0.5 @windMaterial.attributes.windFactor.value[i] = r * r * r # Create mesh mesh = new THREE.Mesh( geometry, @windMaterial ) mesh.position.set( x, y, z ) return mesh
<br>
#以上是如何開發優秀的HTML5遊戲-迪士尼《尋找奧茲之路》遊戲技術詳解(二)的詳細內容。更多資訊請關注PHP中文網其他相關文章!