- BabylonJS 教程
- BabylonJS - 主页
- BabylonJS - 简介
- BabylonJS - 环境设置
- BabylonJS - 概述
- BabylonJS - 基本元素
- BabylonJS - 材料
- BabylonJS - 动画
- BabylonJS - 相机
- BabylonJS - 灯
- BabylonJS - 参数化形状
- BabylonJS - 网格
- 矢量位置和旋转
- BabylonJS - 贴花
- BabylonJS - Curve3
- BabylonJS - 动态纹理
- BabylonJS - 视差映射
- BabylonJS - 镜头光晕
- BabylonJS - 创建屏幕截图
- BabylonJS - 反射探针
- 标准渲染管线
- BabylonJS - 着色器材质
- BabylonJS - 骨骼和骨骼
- BabylonJS - 物理引擎
- BabylonJS - 播放声音和音乐
- BabylonJS 有用资源
- BabylonJS - 快速指南
- BabylonJS - 有用的资源
- BabylonJS - 讨论
BabylonJS - 网格
在本章中,我们将学习使用网格生成器创建不同的形状。我们已经在前面的一章中学习了如何创建形状。
不同之处在于,使用 meshbuilder 可以灵活地向形状添加颜色、图像。
使用 MeshBuilder 创建框
现在让我们看看如何使用 MeshBuilder 创建盒子。
演示
<!doctype html>
<html>
<head>
<meta charset = "utf-8">
<title>BabylonJs - Basic Element-Creating Scene</title>
<script src = "babylon.js"></script>
<style>
canvas {width: 100%; height: 100%;}
</style>
</head>
<body>
<canvas id = "renderCanvas"></canvas>
<script type = "text/javascript">
var canvas = document.getElementById("renderCanvas");
var engine = new BABYLON.Engine(canvas, true);
var createScene = function() {
var scene = new BABYLON.Scene(engine);
scene.clearColor = new BABYLON.Color3(0, 0, 1);
var camera = new BABYLON.ArcRotateCamera("Camera", 1, 0.8, 10, new BABYLON.Vector3(0, 0, 0), scene);
camera.attachControl(canvas, true);
var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);
light.intensity = 0.7;
var pl = new BABYLON.PointLight("pl", BABYLON.Vector3.Zero(), scene);
pl.diffuse = new BABYLON.Color3(1, 1, 1);
pl.specular = new BABYLON.Color3(1, 1, 1);
pl.intensity = 0.8;
var mat = new BABYLON.StandardMaterial("mat1", scene);
mat.alpha = 1.0;
mat.diffuseColor = new BABYLON.Color3(0, 1, 0);
var texture = new BABYLON.Texture("images/cube.png", scene);
mat.diffuseTexture = texture;
var hSpriteNb = 3; // 3 sprites per raw
var vSpriteNb = 2; // 2 sprite raws
var faceUV = new Array(6);
for (var i = 0; i < 6; i++) {
faceUV[i] = new BABYLON.Vector4(i/hSpriteNb, i/vSpriteNb, (i+1)/hSpriteNb, (i+1)/vSpriteNb);
}
var options = {
width: 1.5,
height: 1.5,
depth: 1.5,
faceUV: faceUV
};
var box = BABYLON.MeshBuilder.CreateBox("box", options, scene);
box.material = mat;
scene.registerBeforeRender(function() {
pl.position = camera.position;
});
return scene;
};
var scene = createScene();
engine.runRenderLoop(function() {
scene.render();
});
</script>
</body>
</html>
输出
上面的代码行生成以下输出 -
对于上面的示例,我们使用了精灵图像,如下所示。它有水平 3 列和垂直 2 行。
在这个演示中,我们使用了一个名为cube.png的图像。图片存储在本地的images/文件夹中,也粘贴在下面以供参考。请注意,cube.png 是一个精灵图像,精灵图像是图像的集合。我们想在立方体上显示图像,因此希望立方体的所有侧面都在一起。您还可以下载您选择的类似精灵图像并在演示链接中使用。
createBox 构建器为您提供尺寸选项。
例如,
var box = BABYLON.MeshBuilder.CreateBox("box", options, scene);
演示
var hSpriteNb = 3; // 3 sprites per raw ie colums horizontally as shown in the image
var vSpriteNb = 2; // 2 sprite raws as shown in the image above.
var faceUV = new Array(6); // the cube has 6 sides so creating array for same.
for (var i = 0; i < 6; i++) {
faceUV[i] = new BABYLON.Vector4(i/hSpriteNb, i/vSpriteNb, (i+1)/hSpriteNb, (i+1)/vSpriteNb);
}
var options = {
width: 1.5,
height: 1.5,
depth: 1.5,
faceUV: faceUV
};
这称为使用 createBox 方法将纹理应用到网格构建器。我们使用了图像cube.png,它具有水平 3 列和垂直 2 行。立方体或盒子有 6 个边。
为了应用纹理,我们使用选项参数。例如,
Var box = BABYLON.MeshBuilder.CreateBox ('box', options, scene);
我们定义了一个名为faceUV的数组,大小为6,它们是立方体的边。该数组将始终包含 Vector4 元素。每个 Vector4(x, y, z, w) 定义如下 -
- x = 下底
- y = V 底部
- z = 乌托普
- w = 顶峰
向量的范围是 [0, 1]。Ubottom 和 Vbottom 是纹理裁剪开始处的左下点的 2D 坐标。Utop、Vtop 是纹理裁剪结束的右上角点。
var hSpriteNb = 3; // 3 sprites per raw
var vSpriteNb = 2; // 2 sprite raws
var faceUV = new Array(6);
for (var i = 0; i < 6; i++) {
faceUV[i] = new BABYLON.Vector4(i/hSpriteNb, i/vSpriteNb, (i+1)/hSpriteNb, (i+1)/vSpriteNb);
}
假设默认纹理(即给定的图像)应用于框的所有面。如果您只想更改框的 1 个面或 1 个边,您可以直接指定值,如下所示 -
var hSpriteNb = 3; // 3 sprites per raw var vSpriteNb = 2; // 2 sprite raws var faceUV = new Array(6); faceUV[4] = new BABYLON.Vector4(0, 0, 1/hSpriteNb, 1/vSpriteNb);
例子
<!doctype html>
<html>
<head>
<meta charset = "utf-8">
<title>BabylonJs - Basic Element-Creating Scene</title>
<script src = "babylon.js"></script>
<style>
canvas {width: 100%; height: 100%;}
</style>
</head>
<body>
<canvas id = "renderCanvas"></canvas>
<script type = "text/javascript">
var canvas = document.getElementById("renderCanvas");
var engine = new BABYLON.Engine(canvas, true);
var createScene = function() {
var scene = new BABYLON.Scene(engine);
scene.clearColor = new BABYLON.Color3(0, 0, 1);
var camera = new BABYLON.ArcRotateCamera("Camera", 1, 0.8, 10, new BABYLON.Vector3(0, 0, 0), scene);
camera.attachControl(canvas, true);
var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);
light.intensity = 0.7;
var pl = new BABYLON.PointLight("pl", BABYLON.Vector3.Zero(), scene);
pl.diffuse = new BABYLON.Color3(1, 1, 1);
pl.specular = new BABYLON.Color3(1, 1, 1);
pl.intensity = 0.8;
var mat = new BABYLON.StandardMaterial("mat1", scene);
mat.alpha = 1.0;
mat.diffuseColor = new BABYLON.Color3(0.8, 0.8, 0.8);
var texture = new BABYLON.Texture("images/3d.png", scene);
mat.diffuseTexture = texture;
var hSpriteNb = 3; // 3 sprites per raw
var vSpriteNb = 2; // 2 sprite raws
var faceUV = new Array(6);
faceUV[4] = new BABYLON.Vector4(0, 0, 1/hSpriteNb, 1/vSpriteNb);
var options = {
width:3,
height:3,
depth: 3,
faceUV:faceUV
};
var box = BABYLON.MeshBuilder.CreateBox("box", options, scene);
box.material = mat;
scene.registerBeforeRender(function() {
pl.position = camera.position;
});
return scene;
};
var scene = createScene();
engine.runRenderLoop(function() {
scene.render();
});
</script>
</body>
</html>
输出
上面的代码行生成以下输出 -
在此演示中,我们使用了名为 3d.png 的图像。图片存储在本地的images/文件夹中,也粘贴在下面以供参考。请注意 3d.png 是精灵图像;精灵图像是图像的集合。我们想要在立方体上显示图像,并且立方体的所有侧面都在一起。您还可以下载您选择的类似精灵图像并在演示链接中使用。
用于盒子的纹理 - images/3d.png
网状圆柱体
在本节中,我们将了解如何创建 MeshCylinder。
要创建MeshCylinder,您需要使用类BABYLON.MeshBuilder.CreateCylinder。
该类的参数如下 -
var meshcylinder = BABYLON.MeshBuilder.CreateCylinder("meshcylinder", {
height: 3,
diameter: 35,
tessellation: 52
}, scene);
使用网格和网格构建器的 CreateCylinder 之间的区别是 - 您可以使用网格构建器中的选项。现在我们使用高度、直径和镶嵌作为传递给圆柱体的选项。我们使用带有线框的标准材料作为该网格的材料。检查浏览器中的输出并查看圆柱体。您可以在游戏中使用类似的结构,就像场景中旋转的轮子一样。
演示
<!doctype html>
<html>
<head>
<meta charset = "utf-8">
<title>Babylon.js demo - Mesh Builder</title>
<script src = "babylon.js"></script>
<style>
html,body,canvas { margin: 0; padding: 0; width: 100%; height: 100%; font-size: 0; }
</style>
</head>
<body>
<canvas id = "renderCanvas"></canvas>
<script type = "text/javascript">
var canvas = document.getElementById("renderCanvas");
var engine = new BABYLON.Engine(canvas, true);
var createScene = function() {
var scene = new BABYLON.Scene(engine);
scene.clearColor = new BABYLON.Color3(0.8, 0.8, 0.8);
var camera = new BABYLON.ArcRotateCamera("Camera", -Math.PI / 6, 1.3, 40, new BABYLON.Vector3(0, -3, 0), scene);
var light = new BABYLON.HemisphericLight("hemi", new BABYLON.Vector3(0, 1, 0), scene);
var mat = new BABYLON.StandardMaterial("mat", scene);
mat.diffuseColor = new BABYLON.Color3(0.1, .5, 0);
mat.specularColor = new BABYLON.Color3(0, 0, 0);
mat.wireframe = true;
var meshcylinder = BABYLON.MeshBuilder.CreateCylinder("meshcylinder", {
height: 3,
diameter: 35,
tessellation: 52
}, scene);
meshcylinder.material = mat;
meshcylinder.position = new BABYLON.Vector3(0, 0, 0);
scene.activeCamera.attachControl(canvas);
return scene;
};
var scene = createScene();
engine.runRenderLoop(function() {
scene.render();
});
</script>
</body>
</html>
输出
上面的代码行生成以下输出 -
现在,将在一个演示中一起使用使用网格生成器创建的许多形状。下面的演示链接中涵盖的形状将在后续部分中列出。
BabylonJS – 网格交点和点
游戏中的网格相交非常重要,因为您知道游戏中两个对象相交时需要做什么。下面的演示中对网格相交时需要捕获的事件解释了相同的概念。
在下面给出的演示中,我们涵盖了以下两个概念 -
- 相交网格
- 交点
<!doctype html>
<html>
<head>
<meta charset = "utf-8">
<title>BabylonJs - Basic Element-Creating Scene</title>
<script src = "babylon.js"></script>
<style>
canvas {width: 100%; height: 100%;}
</style>
</head>
<body>
<canvas id = "renderCanvas"></canvas>
<script type = "text/javascript">
var canvas = document.getElementById("renderCanvas");
var engine = new BABYLON.Engine(canvas, true);
var createScene = function() {
var scene = new BABYLON.Scene(engine);
scene.clearColor = new BABYLON.Color3(1, 1, 1);
var camera = new BABYLON.ArcRotateCamera("ArcRotateCamera", 1, 0.8, 20, new BABYLON.Vector3(0, 0, 0), scene);
camera.attachControl(canvas, true);
var matcone = new BABYLON.StandardMaterial("mat1", scene);
matcone.alpha = 1.0;
matcone.diffuseColor = new BABYLON.Color3(0, 0, 0);
matcone.wireframe = true;
var cone = BABYLON.MeshBuilder.CreateCylinder("cone", {height : 10, diameterTop: 10,diameterBottom:10, tessellation: 5}, scene);
cone.position= new BABYLON.Vector3(12,1,0);
cone.material = matcone;
var balloon1 = BABYLON.Mesh.CreateSphere("balloon1",5, 1.0, scene);
var balloon2 = BABYLON.Mesh.CreateSphere("balloon2", 5, 1.0, scene);
var balloon3 = BABYLON.Mesh.CreateSphere("balloon3", 5, 1.0, scene);
balloon1.material = new BABYLON.StandardMaterial("matBallon", scene);
balloon2.material = new BABYLON.StandardMaterial("matBallon", scene);
balloon3.material = new BABYLON.StandardMaterial("matBallon", scene);
balloon1.position = new BABYLON.Vector3(4, 2, 0);
balloon2.position = new BABYLON.Vector3(5, 1, 0);
balloon3.position = new BABYLON.Vector3(7, 0, 0);
var pointToIntersect = new BABYLON.Vector3(10, 0, 0);
var a = 0.01;
scene.registerBeforeRender(function () {
if (balloon1.intersectsMesh(cone, false)) {
balloon1.material.emissiveColor = new BABYLON.Color3(1, 0, 0);
} else {
balloon1.material.emissiveColor = new BABYLON.Color3(0, 1, 0);
}
if (balloon2.intersectsMesh(cone, false)) {
balloon2.material.emissiveColor = new BABYLON.Color3(1, 0, 0);
} else {
balloon2.material.emissiveColor = new BABYLON.Color3(0, 1, 0);
}
if (balloon3.intersectsMesh(cone, false)) {
balloon3.material.emissiveColor = new BABYLON.Color3(1, 0, 0);
} else {
balloon3.material.emissiveColor = new BABYLON.Color3(0, 1, 0);
}
if (balloon3.intersectsPoint(pointToIntersect)) {
balloon3.material.emissiveColor = new BABYLON.Color3(0, 0, 0);
}
a += 0.01;
balloon1.position.x += Math.cos(a) / 10;
balloon2.position.x += Math.cos(a) / 10;
balloon3.position.x += Math.cos(a) / 10;
});
return scene;
};
var scene = createScene();
engine.runRenderLoop(function() {
scene.render();
});
</script>
</body>
</html>
输出
上面的代码生成以下输出 -
解释
通过上面的代码,我们创建了一个线框为 true 的圆柱体。我们创建了 3 个球体。球体的原始颜色是绿色。
在scene.registerBeforeRender函数中,我们将根据与网格(此处为圆柱体)的交集来更改球体的颜色。
考虑registerBeforeRender中的以下代码-
if (balloon1.intersectsMesh(cone, false)) {
balloon1.material.emissiveColor = new BABYLON.Color3(1, 0, 0);
} else {
balloon1.material.emissiveColor = new BABYLON.Color3(0, 1, 0);
}
intersectsMesh如果与传递给它的参数中给定的网格相交,则给出 true 或 false。
例如,
balloon1.intersectsMesh(cone, false); //cone refers to the cylinder mesh here.
与圆柱体相交的球体颜色变为红色;否则,它是绿色的。
以下代码用于相交点 -
var pointToIntersect = new BABYLON.Vector3(10, 0, 0);
if (balloon3.intersectsPoint(pointToIntersect)) {
balloon3.material.emissiveColor = new BABYLON.Color3(0, 0, 0);
}
这里,pointtoIntersect变量是位置向量,在 x 轴上为 10。如果球体穿过交点,球体的颜色将变为黑色。
BabylonJS – 网格拾取碰撞
选择碰撞实际上会为您提供坐标,您可以将网格物体放置在该位置。对象是通过鼠标拾取的,您只需将鼠标单击的位置放置即可。考虑您需要将网格(对象)放置在用户单击鼠标的位置;因此,在拾取碰撞的帮助下,它可以帮助您获得单击位置的坐标。
演示
<!doctype html>
<html>
<head>
<meta charset = "utf-8">
<title>BabylonJs - Basic Element-Creating Scene</title>
<script src = "babylon.js"></script>
<style>
canvas {width: 100%; height: 100%;}
</style>
</head>
<body>
<canvas id = "renderCanvas"></canvas>
<script type = "text/javascript">
var canvas = document.getElementById("renderCanvas");
var engine = new BABYLON.Engine(canvas, true);
var createScene = function() {
var scene = new BABYLON.Scene(engine);
scene.clearColor = new BABYLON.Color3(1, 1, 1);
// setup environment
var light0 = new BABYLON.PointLight("Omni", new BABYLON.Vector3(0, 10, 20), scene);
var freeCamera = new BABYLON.FreeCamera("FreeCamera", new BABYLON.Vector3(0, 0, -30), scene);
var balloon1 = BABYLON.Mesh.CreateSphere("balloon1",5, 1.0, scene);
var balloon2 = BABYLON.Mesh.CreateSphere("balloon2", 5, 1.0, scene);
balloon1.material = new BABYLON.StandardMaterial("matBallon", scene);
balloon2.material = new BABYLON.StandardMaterial("matBallon", scene);
balloon1.position = new BABYLON.Vector3(0, 0, -0.1);
balloon2.position = new BABYLON.Vector3(0, 0, -0.1);
balloon1.material.emissiveColor = new BABYLON.Color3(1, 0, 0);
balloon2.material.emissiveColor = new BABYLON.Color3(0, 0, 1);
//Wall
var wall = BABYLON.Mesh.CreatePlane("wall", 30.0, scene);
wall.material = new BABYLON.StandardMaterial("wallMat", scene);
wall.material.emissiveColor = new BABYLON.Color3(0.5, 1, 0.5);
//When pointer down event is raised
scene.onPointerDown = function (evt, pickResult) {
// if the click hits the ground object, we change the impact position
if (pickResult.hit) {
var dateValue = new Date();
var secondNumber = dateValue.getSeconds();
if (secondNumber % 2 == 0) {
balloon1.position.x = pickResult.pickedPoint.x;
balloon1.position.y = pickResult.pickedPoint.y;
} else {
balloon2.position.x = pickResult.pickedPoint.x;
balloon2.position.y = pickResult.pickedPoint.y;
}
}
};
return scene;
};
var scene = createScene();
engine.runRenderLoop(function() {
scene.render();
});
</script>
</body>
</html>
输出
解释
在上面的示例中,我们使用了一个平面和 2 个球体。要生成此输出,请使用以下代码 -
scene.onPointerDown = function (evt, pickResult) {
// if the click hits the ground object, we change the impact position
if (pickResult.hit) {
var dateValue = new Date();
var secondNumber = dateValue.getSeconds();
if (secondNumber % 2 == 0) {
balloon1.position.x = pickResult.pickedPoint.x;
balloon1.position.y = pickResult.pickedPoint.y;
} else {
balloon2.position.x = pickResult.pickedPoint.x;
balloon2.position.y = pickResult.pickedPoint.y;
}
}
};
事件scene.onPointerDown为您提供协调的 -x、y 和 z,在我们的示例中为pickResult。
如果您单击地面网格物体,它会将 pickResult.hit 设为 true。我们考虑奇数/偶数秒并更改球体的位置以选取结果 z 和 y 坐标,如上所示。位置更改后,球体将放置在您单击并放置鼠标的位置。您可以尝试上面的演示。
BabylonJS – 光线投射
光线投射就像太阳光线,用于检查场景中的碰撞和交叉。
句法
var ray = new BABYLON.Ray(origin, direction, length);
参数
考虑光线投射的以下参数 -
原点- 光线开始的地方。
方向- 射线方向计算如下 -
var forward = new BABYLON.Vector3(0,0,1); forward = vecToLocal(forward, box); var direction = forward.subtract(origin);
然后,为了获得方向,我们从原点(即盒子位置)中减去它 -
长度- 射线的长度。
演示
<!doctype html>
<html>
<head>
<meta charset = "utf-8">
<title>BabylonJs - Basic Element-Creating Scene</title>
<script src = "babylon.js"></script>
<style>
canvas {width: 100%; height: 100%;}
</style>
</head>
<body>
<canvas id = "renderCanvas"></canvas>
<script type = "text/javascript">
var canvas = document.getElementById("renderCanvas");
var engine = new BABYLON.Engine(canvas, true);
var createScene = function() {
var scene = new BABYLON.Scene(engine);
var light = new BABYLON.PointLight("Omni", new BABYLON.Vector3(0, 100, 100), scene);
var camera = new BABYLON.ArcRotateCamera("Camera", 0, 0.8, 100, new BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvas, true);
var ground = BABYLON.Mesh.CreateGround("ground", 500, 500, 10, scene);
var box = BABYLON.Mesh.CreateBox("box", 4.0, scene);
box.position.y = 2;
box.scaling.z = 2;
var matBox = new BABYLON.StandardMaterial("matBox", scene);
matBox.diffuseColor = new BABYLON.Color3(0.8, 0.1, 0.5);
box.material = matBox;
box.isPickable = false;
var box2 = BABYLON.Mesh.CreateBox("box2", 8.0, scene);
box2.position = new BABYLON.Vector3(-20, 4, 0);
var matBox2 = new BABYLON.StandardMaterial("matBox2", scene);
matBox2.diffuseColor = new BABYLON.Color3(1, 0, 0);
box2.material = matBox2;
var box3 = BABYLON.Mesh.CreateBox("box3", 8.0, scene);
box3.position = new BABYLON.Vector3(20, 4, 0);
var matBox3 = new BABYLON.StandardMaterial("matBox3", scene);
matBox3.diffuseColor = new BABYLON.Color3(1, 0, 0);
box3.material = matBox3;
var box4 = BABYLON.Mesh.CreateBox("box4", 8.0, scene);
box4.position = new BABYLON.Vector3(0, 0, 20);
var matBox4 = new BABYLON.StandardMaterial("matBox4", scene);
matBox4.diffuseColor = new BABYLON.Color3(0, 1, 0);
box4.material = matBox4;
var box5 = BABYLON.Mesh.CreateBox("box5", 8.0, scene);
box5.position = new BABYLON.Vector3(0, 0, -20);
var matBox5 = new BABYLON.StandardMaterial("matBox5", scene);
matBox5.diffuseColor = new BABYLON.Color3(0, 1, 0);
box5.material = matBox5;
function mousemovef() {
var pickResult = scene.pick(scene.pointerX, scene.pointerY);
if (pickResult.hit) {
var diffX = pickResult.pickedPoint.x - box.position.x;
var diffY = pickResult.pickedPoint.z - box.position.z;
box.rotation.y = Math.atan2(diffX,diffY);
}
}
scene.onPointerMove = function () {
mousemovef();
};
function vecToLocal(vector, mesh) {
var m = mesh.getWorldMatrix();
var v = BABYLON.Vector3.TransformCoordinates(vector, m);
return v;
}
scene.registerBeforeRender(function () {
var origin = box.position;
var forward = new BABYLON.Vector3(0,0,1);
forward = vecToLocal(forward, box);
var direction = forward.subtract(origin);
direction = BABYLON.Vector3.Normalize(direction);
var length = 100;
var ray = new BABYLON.Ray(origin, direction, length);
// ray.show(scene, new BABYLON.Color3(1, 1, 0.1));
var hit = scene.pickWithRay(ray);
if (hit.pickedMesh) {
hit.pickedMesh.scaling.y += 0.01;
}
});
return scene;
};
var scene = createScene();
engine.runRenderLoop(function() {
scene.render();
});
</script>
</body>
</html>
输出
上面的代码行生成以下输出 -
解释
中心有一个主盒子,充当光线投射。当它指向任何一个盒子时,盒子的大小就会增加。事实证明,这个概念在玩游戏时非常有用,可以了解哪个其他物体正在接触并可以采取必要的行动。
添加box.isPickable = false; 这样就不考虑中心的主框了。如果您不希望任何物体包含在光线中进行接触,请添加box.isPickable = false; 到它。
以下代码添加了由射线拾取的框的缩放。
scene.registerBeforeRender(function () {
var origin = box.position;
var forward = new BABYLON.Vector3(0,0,1);
forward = vecToLocal(forward, box);
var direction = forward.subtract(origin);
direction = BABYLON.Vector3.Normalize(direction);
var length = 100;
var ray = new BABYLON.Ray(origin, direction, length);
var hit = scene.pickWithRay(ray);
if (hit.pickedMesh) {
hit.pickedMesh.scaling.y += 0.01;
}
});
var ray = new BABYLON.Ray(原点、方向、长度); 创建一条射线,并将主框位置作为原点。
射线方向计算如下 -
var forward = new BABYLON.Vector3(0,0,1); forward = vecToLocal(forward, box); var direction = forward.subtract(origin);
然后,为了获得方向,我们从原点(即盒子位置)中减去它。函数vecToLocal旨在通过将向量乘以网格矩阵来从网格角度转换位置。
我们使用var hit = scene.pickWithRay(ray);从射线中获取命中点
它给出了光线与网格重合的位置。
缩放应用于通过执行以下代码行拾取的网格 -
if (hit.pickedMesh) {
hit.pickedMesh.scaling.y += 0.01;
}
在浏览器中尝试上面的示例以查看输出。
带有谓词函数的光线投射
现在让我们看看带有谓词函数的 raycast 是如何工作的以及 rayhelper 显示的方向。
演示
<!doctype html>
<html>
<head>
<meta charset = "utf-8">
<title>BabylonJs - Basic Element-Creating Scene</title>
<script src = "babylon.js"></script>
<style>
canvas {width: 100%; height: 100%;}
</style>
</head>
<body>
<canvas id = "renderCanvas"></canvas>
<script type = "text/javascript">
var canvas = document.getElementById("renderCanvas");
var engine = new BABYLON.Engine(canvas, true);
var createScene = function() {
var scene = new BABYLON.Scene(engine);
var light = new BABYLON.PointLight("Omni", new BABYLON.Vector3(0, 100, 100), scene);
var camera = new BABYLON.ArcRotateCamera("Camera", 0, 0.8, 100, new BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvas, true);
var ground = BABYLON.Mesh.CreateGround("ground", 500, 500, 10, scene);
var box = BABYLON.Mesh.CreateBox("box", 4.0, scene);
box.position.y = 2;
box.scaling.z = 2;
var matBox = new BABYLON.StandardMaterial("matBox", scene);
matBox.diffuseColor = new BABYLON.Color3(0.8, 0.1, 0.5);
box.material = matBox;
box.isPickable = false;
var box2 = BABYLON.Mesh.CreateBox("box2", 8.0, scene);
box2.position = new BABYLON.Vector3(-20, 4, 0);
var matBox2 = new BABYLON.StandardMaterial("matBox2", scene);
matBox2.diffuseColor = new BABYLON.Color3(1, 0, 0);
box2.material = matBox2;
var box3 = BABYLON.Mesh.CreateBox("box3", 8.0, scene);
box3.position = new BABYLON.Vector3(20, 4, 0);
var matBox3 = new BABYLON.StandardMaterial("matBox3", scene);
matBox3.diffuseColor = new BABYLON.Color3(1, 0, 0);
box3.material = matBox3;
var box4 = BABYLON.Mesh.CreateBox("box4", 8.0, scene);
box4.position = new BABYLON.Vector3(0, 0, 20);
var matBox4 = new BABYLON.StandardMaterial("matBox4", scene);
matBox4.diffuseColor = new BABYLON.Color3(0, 1, 0);
box4.material = matBox4;
var box5 = BABYLON.Mesh.CreateBox("box5", 8.0, scene);
box5.position = new BABYLON.Vector3(0, 0, -20);
var matBox5 = new BABYLON.StandardMaterial("matBox5", scene);
matBox5.diffuseColor = new BABYLON.Color3(0, 1, 0);
box5.material = matBox5;
//ray showing the direction
var ray = new BABYLON.Ray();
var rayHelper = new BABYLON.RayHelper(ray);
var localMeshDirection = new BABYLON.Vector3(0, 0, -1);
var localMeshOrigin = new BABYLON.Vector3(0, 0, -.4);
var length = 10;
rayHelper.attachToMesh(box, localMeshDirection, localMeshOrigin, length);
rayHelper.show(scene);
function mousemovef() {
var pickResult = scene.pick(scene.pointerX, scene.pointerY);
if (pickResult.hit) {
var diffX = pickResult.pickedPoint.x - box.position.x;
var diffY = pickResult.pickedPoint.z - box.position.z;
box.rotation.y = Math.atan2(diffX,diffY);
}
}
scene.onPointerMove = function () {
mousemovef();
};
function vecToLocal(vector, mesh) {
var m = mesh.getWorldMatrix();
var v = BABYLON.Vector3.TransformCoordinates(vector, m);
return v;
}
scene.registerBeforeRender(function () {
var origin = box.position;
function predicate(mesh) {
if (mesh == box2 || mesh == box || mesh == box5) {
return false;
}
return true;
}
var forward = new BABYLON.Vector3(0,0,1);
forward = vecToLocal(forward, box);
var direction = forward.subtract(origin);
direction = BABYLON.Vector3.Normalize(direction);
var length = 100;
var ray = new BABYLON.Ray(origin, direction, length);
// ray.show(scene, new BABYLON.Color3(1, 1, 0.1));
var hit = scene.pickWithRay(ray, predicate);
if (hit.pickedMesh) {
hit.pickedMesh.scaling.y += 0.01;
}
});
return scene;
};
var scene = createScene();
engine.runRenderLoop(function() {
scene.render();
});
</script>
</body>
</html>
输出
上面的代码行生成以下输出 -
解释
带有谓词函数的光线投射有助于选择我们想要的网格。如果我们不想选择网格,我们可以忽略它。
function predicate(mesh) {
if (mesh == box2 || mesh == box || mesh == box5) {
return false;
}
return true;
}
上述函数给出了射线选择的网格。如果选择的网格是box2、box、box5,则返回false;否则,为真。
您可以尝试上面的示例。
BabylonJS – 网格阴影
阴影根据光线落在所创建的网格上的方式进行渲染。它们在使输出在 3D 世界中看起来更真实方面发挥着重要作用。
现在让我们学习如何使用babylonjs 创建阴影。
句法
var shadowGenerator00 = new BABYLON.ShadowGenerator(shadowsize, light);
参数
考虑以下与网格阴影相关的参数 -
Shadowsize - 阴影的大小。
光- 场景中使用的光。
演示
<!doctype html>
<html>
<head>
<meta charset = "utf-8">
<title>BabylonJs - Basic Element-Creating Scene</title>
<script src = "babylon.js"></script>
<style>
canvas {width: 100%; height: 100%;}
</style>
</head>
<body>
<canvas id = "renderCanvas"></canvas>
<script type = "text/javascript">
var canvas = document.getElementById("renderCanvas");
var engine = new BABYLON.Engine(canvas, true);
var createScene = function() {
var scene = new BABYLON.Scene(engine);
scene.clearColor = new BABYLON.Color3(1, 1, 1);
var camera = new BABYLON.ArcRotateCamera("ArcRotateCamera", 1, 0.8, 20, new BABYLON.Vector3(0, 0, 0), scene);
camera.attachControl(canvas, true);
// light1
var light = new BABYLON.DirectionalLight("dir01", new BABYLON.Vector3(-1, -2, -1), scene);
light.position = new BABYLON.Vector3(20, 40, 20);
var ground01 = BABYLON.Mesh.CreateGround("Spotlight Hard Shadows", 24, 60, 1, scene, false);
var groundMaterial = new BABYLON.StandardMaterial("ground", scene);
groundMaterial.diffuseTexture = new BABYLON.Texture("images/gr1.jpg", scene);
groundMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
groundMaterial.emissiveColor = new BABYLON.Color3(0.2, 0.2, 0.2);
ground01.material = groundMaterial;
ground01.receiveShadows = true;
ground01.position.x = -5;
var box = BABYLON.Mesh.CreateBox("box", 3.0, scene);
box.position.x = -5;
box.position.y = 5;
var shadowGenerator00 = new BABYLON.ShadowGenerator(512, light);
shadowGenerator00.getShadowMap().renderList.push(box);
//shadowGenerator00.usePoissonSampling = true;
//shadowGenerator00.useExponentialShadowMap = true;
shadowGenerator00.useBlurExponentialShadowMap = true;
shadowGenerator00.bias = 0.01;
scene.registerBeforeRender(function() {
box.rotation.x += 0.01;
box.rotation.x += 0.01;
});
return scene;
};
var scene = createScene();
engine.runRenderLoop(function() {
scene.render();
});
</script>
</body>
</html>
输出
上面的代码行生成以下输出 -
解释
要创建阴影,您需要创建阴影生成器。考虑如下所示的示例。
var shadowGenerator00 = new BABYLON.ShadowGenerator(512, light);
要定义需要阴影的网格,您需要将其添加到上面的生成器中。
shadowGenerator00.getShadowMap().renderList.push(box);
现在,我们创建了一个地面并在其顶部创建了一个盒子。我们希望盒子的影子落在地上。为此,我们需要确保地面被标记为接收阴影,具体操作如下 -
ground01.receiveShadows = true;
有一些可用于阴影的过滤器,如下所示 -
shadowGenerator.usePoissonSampling = true; - Called Poisson sampling shadowGenerator.useExponentialShadowMap = true; - Exponential Shadow Map shadowGenerator.useBlurExponentialShadowMap= true; - Blur Exponential Shadow Map
在我们的演示中,我们使用了shadowGenerator00.useBlurExponentialShadowMap = true; 您可以尝试其他方法并查看输出结果。
在这里,我们使用了名为 gr1.jpg 的图像。图像存储在本地的 images/ 文件夹中。您可以下载您选择的任何图像并在演示链接中使用。
BabylonJS – 网格上的高级纹理
在本节中,我们将了解网格上的高级纹理。不同的纹理如下所示 -
让我们向网格应用一些复杂的纹理 - 镜子、凹凸、视频和折射。
| 先生。 | 网格及描述 |
|---|---|
| 1 | 网格高光层
高光图层用于突出显示场景中的网格。您可以为其指定颜色,并将颜色应用于网格的边框。如果您想在游戏中突出显示,可以使用网格突出显示层。 |
| 2 | 变形网格
变形通过某种过渡方式将一个对象的形状更改为另一个对象的形状。我们已经看到了形状的可更新参数;否则该参数设置为 false。对于变形,将其设置为 true 并更新网格以更改形状。 |
| 3 | 网格动作
动作用于向网格添加交互。当您单击网格或网格相交或碰撞时,事件将被激活。 |
| 4 | 网格资产管理器
使用assestsmanager类,您可以在场景中加载网格、图像和二进制文件。 |
| 5 | 导入网格
我们将学习使用导入网格。 |
| 6 | 网格变形目标
我们已经看到了线、带、多边形等的变形。现在,我们将在这个演示中看到球体和盒子的变形。通过变形目标,球体的形状发生了变化,如下面的演示所示。 |
| 7 | 网格实例
如果您想在场景中绘制相同的网格,请使用实例。 |
| 8 | 网格 LOD 和实例
LOD 代表距离线。此功能允许您根据观察者的距离指定网格。随着观察者到对象的距离增加,网格的细节级别会使用 LOD 清晰显示。 |
| 9 | 网格体积光散射后处理
此过程会散射光,如下面给出的输出所示。在浏览器中进行相同的测试,您将看到光线如何通过网格散射。 |
| 10 | 网格边缘渲染器
EdgesRendering 用于在网格周围绘制边缘,如上面的输出所示。 |
| 11 | 网格混合模式
您可以通过修改材质的 alphamode 来创建混合模式。 |
| 12 | 网格实体粒子
SolidParticle 系统在网格上更新。我们在网格上看到的所有属性都可以用于固体粒子。 |
| 13 | 网格面数据
Facet数据占用大量内存,默认情况下不启用此功能。为了启用它,我们需要根据需要创建一个网格并向其更新面数据。 |