threejs纹理
紋理
紋理用來表現(xiàn)物體的細(xì)節(jié)。理論上可以將物體的每個(gè)細(xì)節(jié)建模出來,但是這樣時(shí)間成本和性能成本都太高,因此,將物體的一些細(xì)節(jié)用紋理來表示。
圖片紋理
圖片紋理直接在物體表面應(yīng)用圖片。可以使用TextureLoader類的load方法來加載紋理。
function loadImgTexture(){var loader = new THREE.TextureLoader();loader.load("metal-rust.jpg",function(texture){var geometry = new THREE.BoxGeometry(10,10,10);var material = new THREE.MeshBasicMaterial({color:0x739783,map:texture});mesh = new THREE.Mesh(geometry,material);scene.add(mesh);}) }注意加載圖片是異步的,所以這里我們使用render循環(huán)來渲染:
function render(){requestAnimationFrame(render);renderer.render(scene,camera); }凹凸貼圖
凹凸貼圖可以使紋理也有厚度,看起來更立體。凹凸貼圖一般使用一張灰度圖,設(shè)置成材料的bumpMap屬性
function loadImgTexture(){var loader = new THREE.TextureLoader();loader.load("stone.jpg",function(texture){loader.load("stone-bump.jpg",function(bumpTexture){var geometry = new THREE.BoxGeometry(10,10,10);var material = new THREE.MeshPhongMaterial({map:texture,bumpMap:bumpTexture,bumpScale:0.2});mesh = new THREE.Mesh(geometry,material);mesh.rotation.x = 30/180Math.PI;scene.add(mesh);})}) }凹凸貼圖雖然看起來更立體,但是其只是有深度,沒有方向,所以只有在某個(gè)方向看是很立體,在其它方向看又不好。如果貼圖的對(duì)象不怎么轉(zhuǎn)動(dòng),光線也不怎么變化,倒可以使用凹凸貼圖。
法向貼圖
法向貼圖使用一張法向圖來表示紋理圖片某個(gè)點(diǎn)的法向量。即用一張圖片保存另一張圖片的法向量信息,然后再在threejs中將這兩個(gè)圖片的信息合在一起,就形成了一個(gè)細(xì)節(jié)豐富的立體紋理。創(chuàng)建法向貼圖如下,注意這里不要再使用MeshBasicMaterial:
function loadImgTexture(){var loader = new THREE.TextureLoader();loader.load("plaster.jpg",function(texture){loader.load("plaster-normal.jpg",function(normalTexture){var geometry = new THREE.BoxGeometry(10,10,10);var material = new THREE.MeshPhongMaterial({map:texture,normalMap:normalTexture,bumpScale:0.2});mesh = new THREE.Mesh(geometry,material);mesh.rotation.x = 30/180Math.PI;scene.add(mesh);})}) }法向貼圖可以生成細(xì)節(jié)豐富的紋理,同時(shí)不損害渲染性能。但是法向圖這張圖片創(chuàng)建起來稍有困難,使用Blender或Photo創(chuàng)建。
光照貼圖
環(huán)境貼圖
環(huán)境貼圖是使用上下左右前后六張圖或者一張全景圖來模擬真實(shí)的環(huán)境,threejs會(huì)將這些圖片渲染成無縫的環(huán)境盒子,例子可看【threejs-cubeMap例子】,其中貌似真實(shí)的環(huán)境,球的反光效果,都是用這張全景圖渲染出來的:
球的反光看起來非常逼真,但其實(shí)是假的,也就四并沒有使用光線追蹤來表現(xiàn)出反光效果。光線追蹤是很耗cpu的,所以,使用環(huán)境貼圖即節(jié)約性能,又能表現(xiàn)出很逼真的效果。
UV貼圖
關(guān)于uv貼圖,【blender wiki】里面說得很好:
UV貼圖是將2D紋理映射到3D物體最靈活的一種方式.在這個(gè)過程中三維曲面網(wǎng)絡(luò)("mesh")的X Y Z被展平到一副二維(X Y 或者說 我們將要看到的 U V)圖片中,這樣圖片中的顏色就被映射到曲面網(wǎng)絡(luò)("mesh")中。 有助于理解UV貼圖的最形象的比喻是切開一個(gè)硬紙盒.盒子是一個(gè)三維物體,正如同加到場景中的一個(gè)曲面網(wǎng)絡(luò)("mesh")方塊. 如果沿著邊縫或折痕剪開盒子,可以把盒子攤開在一個(gè)桌面上.當(dāng)我們從上往下俯視桌子時(shí),我們可以認(rèn)為U是左右方向,V是上下方向.盒子上的圖片就在一個(gè)二維坐標(biāo)中.我們使用U V代表"紋理坐標(biāo)系"來代替通常在三維空間使用的 X Y.如果給模型的每個(gè)面都用一張圖片去貼紋理,這將要加載很多紋理圖片,如果可以只將圖片的某個(gè)部分映射到模型,那就只需要一張圖片就夠了。uv貼圖就能夠?qū)D片的某部分映射到模型的某個(gè)面,如果還不好理解,類比一下CSS Sprite技術(shù)。比如,上一篇【加載3D模型例子】例子中,我們用到了一張圖片:
這張圖里面凌亂的放著攤開的人皮、衣服、手、眼睛等圖片元素。而我們加載出來的模型是這樣的:
在這張圖中,臉是臉,衣服是衣服,都在它們應(yīng)該出現(xiàn)的位置。這便是使用了uv映射,將圖中的某部分作為紋理,貼到模型中的對(duì)應(yīng)部分。
但是,圖中的各個(gè)部分,是怎么和模型對(duì)應(yīng)起來的呢?一個(gè)人的模型有那么多個(gè)面,純手工編碼一個(gè)個(gè)去對(duì)應(yīng),感覺會(huì)出人命。其實(shí),uv貼圖一般是做模型的時(shí)候就做好了,圖和模型的對(duì)應(yīng)關(guān)系也包含在模型文件(就是那個(gè).dae文件)中了,編程的時(shí)候一般是不用關(guān)心這個(gè)。
雖說如此,我們加載模型之后,也可以通過Geometry對(duì)象的faceVertexUvs屬性看看具體是怎么映射的。簡單起見,創(chuàng)建一個(gè)BoxGometry,查看一個(gè)其內(nèi)置的uv映射:
var geom = new THREE.BoxGeometry(24, 24, 24); console.log(geom.faceVertexUvs);打印出:
是一個(gè)有12個(gè)元素的數(shù)組,12代表的就是立方體的12個(gè)三角面。再看數(shù)組的具體某一個(gè)元素:
又是一個(gè)長度為3的Vector2數(shù)組,代表紋理圖片中的三個(gè)位置,這三個(gè)點(diǎn)圍成的部分就是這個(gè)三角面的紋理。上面的(0,0),(1,0),(1,1)都是比例,0代表0%,1代表100%。點(diǎn)是從右下角開始按逆時(shí)針排列的,比如A(0,0),B(1,0),C(1,1)三點(diǎn),在圖片中圍成的區(qū)域如下:
將這張圖加載到立方體,能更清晰立方體是如何通過uv映射來處理紋理的,【例子】。
【持續(xù)更新看這里】
總結(jié)
- 上一篇: webpack --- [读书笔记]
- 下一篇: Robocode 直线瞄准机器人