webgl天空盒边界缝隙_WebGL three.js进修笔记 法向量网格材质MeshNormalMaterial的引见和建立360度全景天空盒的要领...

本文详细介绍了Three.js中的MeshNormalMaterial材质,这种材质不受颜色影响,仅依赖于每个面的法向量。通过实例展示了如何在球体表面绘制法向量,并通过THREE.ArrowHelper实现。此外,还探讨了如何在菜单面板中设置材质属性,以及360度全景背景的实现方法。同时,提供了完整的代码示例。
摘要由CSDN通过智能技术生成

WebGL进修—-Three.js进修笔记(5)

简朴网格材质 MeshNormalMaterial

MeshNormalMaterial是一种不受衬着时运用的色彩影响的材质,它只与本身每一个面从内到外的法向量有关。法向量在webgl中用途非常普遍,光的反射,以及三维图形的纹理映照都与这个有关。

从图中可以看到,网格的每一面衬着的色彩都是不一样的,假如我们想要在物体外表增加法向量,我们可以运用的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度全景背景可以让人有设身处地的觉得,一切这里的背景运用了全景背景

假如想要运用全景的背景,就须要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();

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值