Three.js紋理(一)


一、概念

3D世界的紋理由圖片組成。將紋理以一定的規則映射到幾何體上,一般是三角形上,那么這個幾何體就有紋理皮膚了。

那么在threejs中,或者任何3D引擎中,紋理應該怎么來實現呢?首先應該有一個紋理類,其次是有一個加載圖片的方法,將這張圖片和這個紋理類捆綁起來。

在threejs中,紋理類由THREE.Texture表示,其構造函數如下所示:

THREE.Texture( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy )

各個參數的意義是:

  • Image:這是一個圖片類型,基本上它有ImageUtils來加載,如下代碼var image = THREE.ImageUtils.loadTexture(url); // url 是一個http://xxxx/aaa.jpg 的類似地址,javascript沒有從本地加載數據的能力,所以沒有辦法從您電腦的C盤加載數據。
  • Mapping:是一個THREE.UVMapping()類型,它表示的是紋理坐標。
  • wrapS:表示x軸的紋理的回環方式,就是當紋理的寬度小於需要貼圖的平面的寬度的時候,平面剩下的部分應該以何種方式貼圖的問題。
  • wrapT:表示y軸的紋理回環方式。 magFilter和minFilter表示過濾的方式,這是OpenGL的基本概念。
  • format:表示加載的圖片的格式,這個參數可以取值THREE.RGBAFormat,RGBFormat等。THREE.RGBAFormat表示每個像素點要使用四個分量表示,分別是紅、綠、藍、透明來表示。RGBFormat則不使用透明,也就是說紋理不會有透明的效果。
  • type:表示存儲紋理的內存的每一個字節的格式,是有符號,還是沒有符號,是整形,還是浮點型。不過這里默認是無符號型(THREE.UnsignedByteType)。
  • anisotropy:各向異性過濾。使用各向異性過濾能夠使紋理的效果更好,但是會消耗更多的內存、CPU、GPU時間。

紋理坐標:

在正常的情況下,你在0.0到1.0的范圍內指定紋理坐標。我們來簡單看一下紋理坐標如下圖:

當我們用一幅圖來做紋理的時候,那么這幅圖就隱示的被賦予了如圖一樣的紋理坐標,這個紋理坐標將被對應到一個形狀上。

二、實例

<!DOCTYPE html>
<html lang="en">
<head>
    <title></title>
    <meta charset="utf-8">
    <style>
        body {
            margin: 0px;
            background-color: #000000;
            overflow: hidden;
        }
    </style>
</head>
<body>

<script src="../js/three.js"></script>

<script>

    var camera, scene, renderer;
    var mesh;

    init();
    animate();

    function init() {

        renderer = new THREE.WebGLRenderer();
        renderer.setSize( window.innerWidth, window.innerHeight );
        document.body.appendChild( renderer.domElement );
        //
        camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
        camera.position.z = 400;
        scene = new THREE.Scene();


        var geometry = new THREE.PlaneGeometry( 500, 300, 1, 1 );
        geometry.vertices[0].uv = new THREE.Vector2(0,0);
        geometry.vertices[1].uv = new THREE.Vector2(2,0);
        geometry.vertices[2].uv = new THREE.Vector2(2,2);
        geometry.vertices[3].uv = new THREE.Vector2(0,2);
        // 紋理坐標怎么弄
        var texture = THREE.ImageUtils.loadTexture("textures/a.jpg",null,function(t)
        {
        });
        var material = new THREE.MeshBasicMaterial({map:texture});
        var mesh = new THREE.Mesh( geometry,material );
        scene.add( mesh );

        //
        window.addEventListener( 'resize', onWindowResize, false );

    }

    function onWindowResize() {
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize( window.innerWidth, window.innerHeight );
    }

    function animate() {
        requestAnimationFrame( animate );
        renderer.render( scene, camera );
    }

</script>

</body>
</html>

上面的代碼,一共完成了4件事情:

  1. 畫一個平面
  2. 為平面賦予紋理坐標
  3. 加載紋理
  4. 將紋理應用於材質

1.畫一個平面

 var geometry = new THREE.PlaneGeometry( 500, 300, 1, 1 );

2.為平面賦予紋理坐標

  平面有4個頂點,所以我們只需要指定4個紋理坐標就行了。紋理坐標由頂點的uv成員來表示,uv被定義為一個二維向量THREE.Vector2(),我們可以通過如下代碼來為平面定義紋理:

geometry.vertices[0].uv = new THREE.Vector2(0,0);
geometry.vertices[1].uv = new THREE.Vector2(1,0);
geometry.vertices[2].uv = new THREE.Vector2(1,1);
geometry.vertices[3].uv = new THREE.Vector2(0,1);

  注意,4個頂點分別對應了紋理的4個頂點。還要注意(0,0),(1,0),(1,1),(0,1)他們之間的順序是逆時針方向。大家在給平面賦紋理坐標的時候也要注意方向,不然three.js是分不清楚的。

3.加載紋理

  紋理作為一張圖片,可以來源於互聯網,或者本地服務器,但是就是不能來源於類似C:\pic\a.jpg這樣的本地路徑。這是因為javascript沒有加載本地路徑文件的權限。

  這里加載紋理使用了上面介紹的loadTexture函數,代碼如下:

var texture=THREE.ImageUtils.loadTexture("textures/a.jpg",null,function(t)
{
});

  這個函數的第一個參數是一個相對路徑,表示與您的網頁之間的相對路徑。相對路徑對應了一個紋理圖片textures/a.jpg。

  第二個參數為null,表示時候要傳入一個紋理坐標參數,來覆蓋前面在geometry中的參數。

  第三個表示一個回調函數,表示成功加載紋理后需要執行的函數,參數t是傳入的texture。

4.將紋理應用於材質

  加載好紋理,萬事俱備了,只需要將紋理映射到材質就可以了。我們這里使用了一個普通的材質THREE.MeshBasicMaterial,材質中有一個map屬性,可以直接接受紋理,我們可以這樣定義一個帶紋理的材質:

var material = new THREE.MeshBasicMaterial({map:texture});

ok,接下來的事情就簡單了,直接將紋理甩給Mesh,同時也別忘了Mesh也需要geometry,他們曖昧的關系如下:

var mesh = new THREE.Mesh( geometry,material );

最后的最后,將這個mesh加入場景中:

scene.add( mesh );


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM