天天看點

webgl天空盒邊界縫隙_WebGL three.js進修筆記 法向量網格材質MeshNormalMaterial的引見和建立360度全景天空盒的要領...

WebGL進修—-Three.js進修筆記(5)

簡樸網格材質 MeshNormalMaterial

MeshNormalMaterial是一種不受襯着時運用的色彩影響的材質,它隻與本身每一個面從内到外的法向量有關。法向量在webgl中用途非常普遍,光的反射,以及三維圖形的紋理映照都與這個有關。

webgl天空盒邊界縫隙_WebGL three.js進修筆記 法向量網格材質MeshNormalMaterial的引見和建立360度全景天空盒的要領...

從圖中可以看到,網格的每一面襯着的色彩都是不一樣的,假如我們想要在物體外表增加法向量,我們可以運用的THREE.ArrowHelper去示意每一個法向量,它的參數為

THREE.ArrowHelper(dir, origin, length, color, headLength, headWidth)

**個中參數的意義為:

dir:方向,默許是法向量

origin:最先的坐标位置

length:輔助線的長度

color:輔助線的色彩

headLength:頭部的長度

headWidth:頭部的寬度**

關于一個球體,要形貌它每一個面的法向量,起首須要對它的每一個面舉行周遊,掏出這個面上的三個極點(由于webgl的面都是三角形,是以是三個極點),經由過程divideScalar(3)這個函數盤算它的中間位置,我們就可以在這個中間位置點上,從内向外引出一個ArrowHelper,來模仿法向量。

for(let i=0;i

let face = sphereGeometry.faces[i];//獲得每一個面的對象

let centroid = new THREE.Vector3();

//先建立一個vector3對象,要運用這個對象找到每一個面的中間

centroid.add(sphereGeometry.vertices[face.a]);

// 将這該面的三個極點的索引傳給sphereGeometry.vertices找到其極點的坐标

//再增加進centroid

centroid.add(sphereGeometry.vertices[face.b]);

centroid.add(sphereGeometry.vertices[face.c]);

centroid.divideScalar(3);//三角形的中間點坐标

let arrow = new THREE.ArrowHelper(

face.normal,//face這個面的法向量

centroid,

2,

0xffcc55,

0.5,

0.5);//箭頭輔助線,相當于把法向量用箭頭示意出來

sphere.add(arrow);

}

個中,centroid.add(sphereGeometry.vertices[face.a])這段代碼中的sphereGeometry.vertices存有幾何體的一切極點資訊,經由過程[ ]索引可以獲得個中的某一個極點。face.a另有下面的face.b和c都是該面的極點索引号,示意這個面是由極點編号為face.a,face.b,face.c的三個極點所組成的一個三角形(webgl的面都是三角形),然後我們再盤算這三個極點的中間點。

菜單面闆的設定

在菜單面闆中設定一些MeshNormalmaterial的一些屬性,便于去測試這類材質的一些特質

個中:

**this.visible = meshMaterial.visible;//是不是可見

this.wireframe = meshMaterial.wireframe;//是不是以線框的體式格局襯着物體

this.wireframeWidth = meshMaterial.wireframeLinewidth;//線框的寬度

this.transparent = meshMaterial.transparent;//是不是通明

this.opacity = meshMaterial.opacity;//通明度,須要transparent為true才有結果

this.side = "front";//邊的襯着體式格局,有三種,前面,背面,另有雙面

this.selectMesh = "sphere";//目前挑選的幾何體

this.shading = "smooth";//着色體式格局,有平面着色戰争滑着色,對一個面很平的幾何體險些看不出區分,如正方體**

function initDatGUI() {

//設定菜單中須要的參數

controls = new function () {

this.rotationSpeed = 0.02;

this.visible = meshMaterial.visible;//是不是可見

this.wireframe = meshMaterial.wireframe;//是不是以線框的體式格局襯着物體

this.wireframeWidth = meshMaterial.wireframeLinewidth;//線框的寬度

this.transparent = meshMaterial.transparent;//是不是通明

this.opacity = meshMaterial.opacity;//通明度,須要transparent為true才有結果

this.side = "front";//邊的襯着體式格局,有三種,前面,背面,另有雙面

this.selectMesh = "sphere";//目前挑選的幾何體

this.shading = "smooth";//着色體式格局,有平面着色戰争滑着色,對一個面很平的幾何體險些看不出區分,如正方體

};

let gui = new dat.GUI();

//将方才設定的參數增加到菜單中

let F1 = gui.addFolder("Mesh");

F1.add(controls, "rotationSpeed", 0, 0.1);

F1.add(controls, "visible").onChange(function (e) {

meshMaterial.visible = e;

});

F1.add(controls, "wireframe").onChange(function (e) {

meshMaterial.wireframe = e;

});

F1.add(controls, "wireframeWidth",0,10).onChange(function (e) {

meshMaterial.wireframeWidth = e;

});

F1.add(controls, "transparent").onChange(function (e) {

meshMaterial.transparent = e;

});

F1.add(controls, "opacity",0,1).onChange(function (e) {

meshMaterial.opacity = e;

});

F1.add(controls, "side",["front","back","double"]).onChange(function (e) {

switch (e) {

case "front":

meshMaterial.side = THREE.FrontSide;

break;

case "back":

meshMaterial.side = THREE.BackSide;

break;

case "double":

meshMaterial.side = THREE.DoubleSide;

break;

}

meshMaterial.needsUpdate = true;//要在遞次中讓材質更新須要增加這一句話

});

F1.add(controls, "selectMesh",["sphere","cube","plane"]).onChange(function (e) {

//先把場景的物體消滅,再來增加

scene.remove(cube);

scene.remove(sphere);

scene.remove(plane);

switch (e) {

case "sphere":

scene.add(sphere);

break;

case "cube":

scene.add(cube);

break;

case "plane":

scene.add(plane);

break;

}

});

F1.add(controls, "shading",["flat","smooth"]).onChange(function (e) {

switch (e) {

case "flat":

meshMaterial.shading = THREE.FlatShading;

break;

case "smooth":

meshMaterial.shading = THREE.SmoothShading;

break;

}

meshMaterial.needsUpdate = true;//要在遞次中讓材質更新須要增加這一句話

});

}

**注意在遞次運轉過程當中想要轉變材質的屬性,須要在改完今後,增加一句

meshMaterial.needsUpdate = true,如許才更新勝利。**

360度全景背景

360度全景背景可以讓人有設身處地的覺得,一切這裡的背景運用了全景背景

webgl天空盒邊界縫隙_WebGL three.js進修筆記 法向量網格材質MeshNormalMaterial的引見和建立360度全景天空盒的要領...

假如想要運用全景的背景,就須要6張6個方向的圖檔來合成一個完全的背景(也可以運用1張6方向的圖檔),然後把這些貼圖指派給 scene.background

let urls =[

'image/posx.jpg',

'image/negx.jpg',

'image/posy.jpg',

'image/negy.jpg',

'image/posz.jpg',

'image/negz.jpg'

];//引入6個方向的貼圖

let cubeMap = THREE.ImageUtils.loadTextureCube( urls );

scene = new THREE.Scene();

scene.background = cubeMap;

這些圖檔的須要根據遞次擺放,右左高低後前,不然背景會紊亂。

這裡給一個全景圖檔的網站,内裡有許多的360度風景圖,都是6張範例的,下載下傳下來解壓後就可以直接引入

http://www.humus.name/index.p…

本例子的完全代碼以下:

Depth Material Test

div#WebGL-output {

border: none;

cursor: pointer;

width: 100%;

height: 850px;

background-color: #333333;

}

let camera, renderer, scene, light;

let controller;

let controls;

let cube, sphere, plane, meshMaterial;

function initThree() {

//襯着器初始化

renderer = new THREE.WebGLRenderer({

antialias: true

});

renderer.setSize(window.innerWidth, window.innerHeight);

renderer.setClearColor(0x333333);

document.getElementById("WebGL-output").appendChild(renderer.domElement);//将襯着增加到div中

//初始化錄影機,這裡運用透視投影錄影機

camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 10, 100);

camera.position.set(0, 40, 60);

camera.up.x = 0;//設定錄影機的上方向為哪一個方向,這裡定義攝像的上方為Y軸正方向

camera.up.y = 1;

camera.up.z = 0;

camera.lookAt(0, 0, 0);

//初始化場景

let urls =[

'image/posx.jpg',

'image/negx.jpg',

'image/posy.jpg',

'image/negy.jpg',

'image/posz.jpg',

'image/negz.jpg'

];//引入6個方向的貼圖

let cubeMap = THREE.ImageUtils.loadTextureCube( urls );

scene = new THREE.Scene();

scene.background = cubeMap;

//相機的挪動

controller = new THREE.OrbitControls(camera, renderer.domElement);

controller.target = new THREE.Vector3(0, 0, 0);

light = new THREE.AmbientLight(0x0c0c0c);

scene.add(light);

// add spotlight for the shadows

light = new THREE.SpotLight(0xffffff);

light.position.set(0, 30, 30);

scene.add(light);

}

//初始化菜單面闆

function initDatGUI() {

//設定菜單中須要的參數

controls = new function () {

this.rotationSpeed = 0.02;

this.visible = meshMaterial.visible;//是不是可見

this.wireframe = meshMaterial.wireframe;//是不是以線框的體式格局襯着物體

this.wireframeWidth = meshMaterial.wireframeLinewidth;//線框的寬度

this.transparent = meshMaterial.transparent;//是不是通明

this.opacity = meshMaterial.opacity;//通明度,須要transparent為true才有結果

this.side = "front";//邊的襯着體式格局,有三種,前面,背面,另有雙面

this.selectMesh = "sphere";//目前挑選的幾何體

this.shading = "smooth";//着色體式格局,有平面着色戰争滑着色,對一個面很平的幾何體險些看不出區分,如正方體

};

let gui = new dat.GUI();

//将方才設定的參數增加到菜單中

let F1 = gui.addFolder("Mesh");

F1.add(controls, "rotationSpeed", 0, 0.1);

F1.add(controls, "visible").onChange(function (e) {

meshMaterial.visible = e;

});

F1.add(controls, "wireframe").onChange(function (e) {

meshMaterial.wireframe = e;

});

F1.add(controls, "wireframeWidth",0,10).onChange(function (e) {

meshMaterial.wireframeWidth = e;

});

F1.add(controls, "transparent").onChange(function (e) {

meshMaterial.transparent = e;

});

F1.add(controls, "opacity",0,1).onChange(function (e) {

meshMaterial.opacity = e;

});

F1.add(controls, "side",["front","back","double"]).onChange(function (e) {

switch (e) {

case "front":

meshMaterial.side = THREE.FrontSide;

break;

case "back":

meshMaterial.side = THREE.BackSide;

break;

case "double":

meshMaterial.side = THREE.DoubleSide;

break;

}

meshMaterial.needsUpdate = true;//要在遞次中讓材質更新須要增加這一句話

});

F1.add(controls, "selectMesh",["sphere","cube","plane"]).onChange(function (e) {

//先把場景的物體消滅,再來增加

scene.remove(cube);

scene.remove(sphere);

scene.remove(plane);

switch (e) {

case "sphere":

scene.add(sphere);

break;

case "cube":

scene.add(cube);

break;

case "plane":

scene.add(plane);

break;

}

});

F1.add(controls, "shading",["flat","smooth"]).onChange(function (e) {

switch (e) {

case "flat":

meshMaterial.shading = THREE.FlatShading;

break;

case "smooth":

meshMaterial.shading = THREE.SmoothShading;

break;

}

meshMaterial.needsUpdate = true;//要在遞次中讓材質更新須要增加這一句話

});

}

function initObject() {

//建立正方體,球和地面的幾何體

let cubeGeometry = new THREE.BoxGeometry(10, 10, 10);

let sphereGeometry = new THREE.SphereGeometry(10, 20, 20);

let planeGeometry = new THREE.PlaneGeometry(10, 10, 1, 1);

//建立一個法向量材質

meshMaterial = new THREE.MeshNormalMaterial();

cube = new THREE.Mesh(cubeGeometry, meshMaterial);

sphere = new THREE.Mesh(sphereGeometry, meshMaterial);

plane = new THREE.Mesh(planeGeometry, meshMaterial);

//把三者的位置一緻

cube.position.set(0,0,0);

sphere.position = cube.position;

plane.position = cube.position;

//在球的每一個面上顯現一個法向量,輕易觀察這類法向量材質的襯着體式格局

for(let i=0;i

let face = sphereGeometry.faces[i];//獲得每一個面的對象

let centroid = new THREE.Vector3();//先建立一個vector3對象,要運用這個對象找到每一個面的中間,

centroid.add(sphereGeometry.vertices[face.a]);

// 将這該面的三個極點的索引傳給sphereGeom.vertices找到其極點的坐标,再增加進centroid

centroid.add(sphereGeometry.vertices[face.b]);

centroid.add(sphereGeometry.vertices[face.c]);

centroid.divideScalar(3);//三角形的中間點坐标

let arrow = new THREE.ArrowHelper(

face.normal,

centroid,

2,

0xffcc55,

0.5,

0.5);//箭頭輔助線,相當于把法向量用箭頭示意出來

sphere.add(arrow);

}

scene.add(sphere);

}

function rotation() {

scene.traverse(function (e) {

if (e instanceof THREE.Mesh) {

e.rotation.y += controls.rotationSpeed;

}

})

}

//襯着函數

function render() {

rotation();

stats.update();

renderer.clear();

requestAnimationFrame(render);

renderer.render(scene, camera);

}

//功用函數

function setting() {

loadFullScreen();

loadAutoScreen(camera, renderer);

loadStats();

}

//運轉主函數,敲代碼的時刻總是敲錯,是以改了一個名字,叫Start更輕易

function Start() {

initThree();

initObject();

initDatGUI();

setting();

render();

}