当前位置: 首页 > news >正文

Babylon.js引擎(二)

三、组件

(4)光源   

引擎自带有多种光源,现示例如下:

点光源示例,核心代码如下:

1    var createScene = function () {                          //创建场景的方法2        var scene = new BABYLON.Scene(engine);               //获取场景对象3        var camera = new BABYLON.ArcRotateCamera("camera1",4             0, 0, 0, new BABYLON.Vector3(0, 0, 0), scene);  //创建弧度旋转相机5        camera.setPosition(new BABYLON.Vector3(0,30,35));   //设置相机的位置6        camera.attachControl(canvas, true);                  //开启控制7        //创建点光源并指定位置8        var light = new BABYLON.PointLight("light", new BABYLON.Vector3(-20, 20, 20),scene);9        light.diffuse=new BABYLON.Color3(1, Math.random(), Math.random());10       light.range=100;                                     //设置光源的照射范围11       light.intensity=1.1;                                //设置光源的强度12       ......//此处省略了向场景中添加网格对象的方法,读者可自行查看随书源代码13       return scene;                                        //返回场景对象14   };

        说明:此段代码的功能为创建场景和弧度旋转相机,设置相机位置并开启控制,创建点光源对象并指定点光源的位置、颜色、照射范围和光照强度。其中向场景添加网格对象的方法与前面案例中的网格对象代码相同,读者可自行查看随书源代码。

聚光灯光源示例,核心代码:

 var createScene = function () {                          //创建场景2         var ambientColor=new BABYLON.Color3(0.2,0.2,0.2);  //地板环境色3         var scene = new BABYLON.Scene(engine);              //设置环境色4         scene.ambientColor=new BABYLON.Color3(1,1,1);      //设置场景环境色5         var camera = new BABYLON.ArcRotateCamera("Camera",6              0, 0.8, 90, BABYLON.Vector3.Zero(), scene);    //创建弧度旋转相机7         camera.lowerBetaLimit = 0.1;                        //设置相机最小的旋转角度8         camera.upperBetaLimit = (Math.PI / 2) * 0.9;       //设置相机最大的旋转角度9         camera.lowerRadiusLimit = 1;                        //设置相机最小的旋转半径10        camera.upperRadiusLimit = 150;                      //设置相机最大的旋转半径11        camera.attachControl(canvas, true);                 //开启控制12        camera.setPosition(new BABYLON.Vector3(-20, 11, -20)); //设置摄像机位置13        var light = new BABYLON.SpotLight("spotLight", new BABYLON.Vector3(-40, 40, -40),14             new BABYLON.Vector3(1, -1, 1), Math.PI / 5, 30, scene); //创建聚光灯光源15        light.position = new BABYLON.Vector3(-40, 40, -40);        //设置聚光灯位置16        light.shadowMaxZ = 100;                            //设置阴影投射的最远距离17        light.shadowMinZ = 10;                             //设置阴影投射的最近距离18        var shadowGenerator = new BABYLON.ShadowGenerator(1024, light); //创建阴影计算对象19        shadowGenerator.bias = 0.001;                      //设置阴影偏移量20        shadowGenerator.normalBias = 0.02;                 //设置正常偏移量21        shadowGenerator.useContactHardeningShadow = true; //开启接触硬化阴影22        shadowGenerator.contactHardeningLightSizeUVRatio = 0.05; //设置阴影的软化速度23        shadowGenerator.setDarkness(0.5);                  //设置暗值24        var meshArray=[];                                   //网格对象数组25        ......//此处省略了创建网格对象的代码,读者可自行查看随书源代码26        var groundMaterial = new BABYLON.StandardMaterial("groundMaterial", scene);//创建地板的材质27        groundMaterial.ambientColor=ambientColor;         //设置地板环境色28        var ground =BABYLON.MeshBuilder.CreateGround("gd", {width: 60, height:60 ,subdivsions: 4}, scene);
29        ground.material=groundMaterial;                    //设置地板材质30        ground.receiveShadows = true;                      //设置地板接收阴影31        var meshMaterial=new BABYLON.StandardMaterial("meshMaterial", scene); //创建材质32        meshMaterial.ambientColor=ambientColor;            //设置材质的环境色33        for(var i=0; i<meshArray.length; i++){               //遍历网格对象数组34             shadowGenerator.getShadowMap().renderList.push(meshArray[7-i]);35             meshArray[i].material=meshMaterial;            //设置各个网格对象的材质36             meshArray[i].material.diffuseColor=new BABYLON.Color3(1, Math.random(),Math.random());37             meshArray[i].position.x=-16+Math.floor(i/2)*10; //设置各个网格对象的 x坐标38             meshArray[i].position.y=4;                       //设置各个网格对象的 y坐标39             meshArray[i].position.z=(i%2==0)? -4:6;          //设置各个网格对象的 z坐标40        }}

、                ❑ 第1~12行代码的功能为创建场景并设置场景的环境色,创建弧度旋转相机并设相机的最小旋转角度、最大旋转角度、最小旋转半径、最大旋转半径和位置以及开启相机控制。
                ❑ 第13~23行的功能为创建聚光灯光源并设置聚光灯光源的阴影投射范围,创建阴影计算对象并设置阴影偏移量、正常偏移量、阴影类型和暗值。其中,接触硬化阴影仅限WebGL 2.0中有。
                ❑ 第24~39行代码的功能为创建地板网格对象并设置其材质与位置,创建不同形状的网格对象并设置材质和位置,以及将它们放入阴影计算列表。
平行光源示例,核心代码 :

        平行光源,示例如下:

QQQ:
1    var createScene = function () {2        var scene = new BABYLON.Scene(engine);               //创建场景3        var camera = new BABYLON.ArcRotateCamera("camera1",4              0, 0, 0, new BABYLON.Vector3(0, 0, 0), scene); //创建弧度旋转摄像机5        camera.setPosition(new BABYLON.Vector3(0,30,35));   //设置弧度旋转相机的位置6        camera.attachControl(canvas, true);                  //开启控制7        var light = new BABYLON.DirectionalLight("DirectionalLight",8             new BABYLON.Vector3(-1, -1, -1), scene);        //创建平行光并指定方向9        light.diffuse=new BABYLON.Color3(1, Math.random(), Math.random());//设置光的颜色10       light.position=new BABYLON.Vector3(30,30,30);       //设置阴影投放的位置11       light.shadowMaxZ = 100;                              //设置最大的投影距离12       light.shadowMinZ = 10;                     //设置最小的投影距离13       ......//此处省略了阴影计算和创建网格对象的代码,读者可自行查看随书源代码14       return scene;                              //返回场景对象15       };

        此段代码的功能为创建场景对象和弧度旋转摄像机,并设置其位置以及开启相机控制,创建平行光并指定其方向、阴影投放位置和投影范围。创建平行光中的第二个参数为光源照射的方向。此外,需特别注意光源的position属性,其设置不当可能导致部分网格对象无法投射出阴影。
 

(5)  材质
       

         对网格对象进行材质设置,网格对象才能更美观地呈现在场景中。材质决定了此网格的颜色、透明度等外观信息。
       

 1.标准材质
     标准材质允许在网格对象上覆盖颜色和纹理,并且需要光线才能看,

示例搭建基本场景,创建4个球体网格对象和标准材质,核心代码如下:

 

1     var canvas = document.getElementById("renderCanvas");   //获取Canvas DOM对象2     var engine = new BABYLON.Engine(canvas, true);          //获取Babylon引擎对象3     var createScene = function () {4         var scene = new BABYLON.Scene(engine);               //获取场景对象5         var camera = new BABYLON.ArcRotateCamera("Camera",6               -Math.PI / 2, 3 * Math.PI / 16, 15, BABYLON.Vector3.Zero(), scene);//创建弧度旋转相机7         camera.attachControl(canvas, true);                  //开启相机控制8         var redMat = new BABYLON.StandardMaterial("redMat", scene);  //创建标准材质9         redMat.emissiveColor = new BABYLON.Color3(1, 0, 0); //设置自发光颜色为红色10        ......//此处省略创建其他球体标准材质的代码,读者可自行查看随书源代码11        var sphereCenter=BABYLON.MeshBuilder.CreateSphere("sphere", {diameter: 0.01}, scene);12        var lightRed = new BABYLON.SpotLight("spotLight",13             new BABYLON.Vector3(), new BABYLON.Vector3(0, -1, 0), Math.PI / 2, 1.5,scene);14        lightRed.diffuse = new BABYLON.Color3(1, 0, 0);    //设置聚光灯颜色为红色15        lightRed.position.set(3,2,3);                       //设置红色聚光灯的位置16        lightRed.parent=sphereCenter;                       //将其父类属性指向中心球17        ......//此处省略创建其他颜色聚光灯光源的代码,读者可自行查看随书源代码18        var redSphere = BABYLON.MeshBuilder.CreateSphere("sphere", {diameter:0.25}, scene);19        redSphere.material = redMat;                     //设置其材质20        redSphere.position = lightRed.position;         //球体位置设为红色聚光灯的位置21        redSphere.parent=sphereCenter;                   //将其父类属性指向中心球22        ......//此处省略创建其他颜色球体网格对象的代码,读者可自行查看随书源代码23        var groundMat = new BABYLON.StandardMaterial("groundMat", scene);//创建地板的标准材质24        var ground = BABYLON.MeshBuilder.CreateGround("ground", {width: 15, height: 15}, scene);25        ground.material = groundMat;                     //设置地板的材质26        var angle=0;                                      //旋转角度27        scene.onBeforeRenderObservable.add(()=>{        //场景渲染之前的执行函数28             angle=angle+0.01;                            //角度增加29             sphereCenter.rotation.set(0, angle,0);30        ......//此处省略Babylon中GUI界面的搭建和控制方法的代码,它将在下文进行详细介绍31    }

                ❑ 第1~6行的功能为获取Canvas DOM对象、Babylon引擎对象、场景对象,创建弧度旋转相机,开启相机控制。
                ❑ 第7~25行为创建4种标准材质并设置为自发光颜色。创建4种不同颜色的聚光灯光源,创建4种不同颜色的球体网格对象,将球体位置设置为对应颜色聚光灯光源的位置,将聚光灯和球体的父类属性都指向中心球,最后创建地板并设置其材质为标准材质。
                ❑ 第26~31行代码为不断旋转中心球,从而实现旋转聚光灯光源和球体网格对象。将聚光灯和球体的父类属性都指向中心球,此时中心球中包含聚光灯和球体。旋转中心球,就会同时旋转聚光灯光源和球体网格对象,读者可以将这个作为一个开发技巧积累下来。

        示例中GUI界面的开发和控制方法的开发。具体代码如下。

1     var advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("UI");//全屏纹理2     var sceneAmbientColorFlag=false;                            //场景环境色开启标志3     var leftPanel= createPanel(advancedTexture,4         BABYLON.GUI.Control.VERTICAL_ALIGNMENT_CENTER,5              BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT);    //左侧面板6     var senceCheckBox=createCheckbox(leftPanel, "开启场景环境颜色",7         BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT);        //创建单选框8     senceCheckBox.onIsCheckedChangedObservable.add(function (value){//单选框控制方法9         sceneAmbientColorFlag=value;                          //更改场景环境色开启标志10        if(! sceneAmbientColorFlag) {                          //如果没开启11             scene.ambientColor=new BABYLON.Color3(0,0,0); }}) //场景环境色设置为黑色12    var senceColorPicker=createColorPicker(leftPanel, false, "",13        scene.ambientColor, BABYLON.GUI.Control.HORIZONTAL_ALIGNMENfuT_CENTER);14    senceColorPicker.onValueChangedObservable.add(function(value) {  //颜色改变事件15        if(sceneAmbientColorFlag) {                     //如果开启场景环境色16             scene.ambientColor.copyFrom(value); }});    //将场景环境色指定为选择的颜色值17    ......//此处省略其他颜色选择器的创建和控制方法的代码,读者可自行查看随书源代码18    function createCheckbox(panel, text, horizontalAlignment) {    //创建单选框19        var checkbox = new BABYLON.GUI.Checkbox();                //新建单选框20        checkbox.width = "20px";                                   //单选框的宽21        checkbox.height = "20px";                                 //单选框的高22        checkbox.isChecked = false;                               //单选框的状态23        checkbox.color = "green";                                 //单选框的颜色24        var header = BABYLON.GUI.Control.AddHeader(checkbox, text, "180px", {//给单选框添加文字头25             isHorizontal: true,26             controlFirst: true});27        header.height = "30px";                          //设置文字头的高度28        header.color = "white";                          //设置文字的颜色29        header.outlineWidth ="4px";                      //轮廓宽度30        header.outlineColor ="black";                    //轮廓颜色31        header.horizontalAlignment=horizontalAlignment; //水平布局32        panel.addControl(header);               //将文字头添加进面板33        return checkbox; }                                //返回单选框对象34    function createPanel(advancedTexture, verticalAlignment, horizontalAlignment) {//创建面板35        var panel = new BABYLON.GUI.StackPanel();       //创建静态的面板36        panel.width = "200px";                           //面板的宽37        panel.verticalAlignment = verticalAlignment;    //面板的垂直布局38        panel.horizontalAlignment = horizontalAlignment; //面板的水平布局39        advancedTexture.addControl(panel);               //添加控制40        return panel; }                                    //返回面板41    function createColorPicker(panel, usetext, text, defultColor, horizontalAlignment){//创建颜色控件42        if(usetext){                                      //如果使用文本控件43             var textBlock = new BABYLON.GUI.TextBlock(); //创建文本控件44             textBlock.text = text;                       //设置文本内容45             textBlock.color = "white";                   //设置文本颜色46             textBlock.height = "30px";                   //文本颜色47             panel.addControl(textBlock); }               //面板中添加文本控件48        var picker = new BABYLON.GUI.ColorPicker();     //创建颜色控件49        picker.value =defultColor;                       //默认颜色50        picker.height = "150px";                         //颜色控件的高51        picker.width = "150px";                          //颜色控件的宽52        picker.horizontalAlignment =horizontalAlignment; //水平布局方式53        panel.addControl(picker)                         //添加控制54        return picker; }                                   //返回颜色控件

        ❑ 第1~18行的功能为创建GUI全屏纹理、左右侧面板、单选框和颜色选择器,其中单选框添加状态改变事件,颜色选择器添加状态改变事件。单选框控制场景环境色的开启,颜色选择器会改变地板材质的环境颜色、漫反射颜色、自发光颜色和镜面颜色。
        ❑ 第18~33行为创建GUI单选框,设置单选框的宽度、高度、状态、颜色,并添加文字头说明单选框的作用。然后设置文字头的高度、文字颜色、轮廓宽度、轮廓颜色和水平布局方式,最后将文字头添加进面板和返回单选框对象。
        ❑ 第34~40行为创建面板,设置面板的宽度,垂直布局和水平布局方式,并添加进GUI全屏纹理,最后返回面板对象。
        ❑ 第41~54行为创建颜色控件,添加文本控件以及设置文本控件的内容、颜色和文本的高度,设置颜色控件的宽度、高度和水平布局方式,最后将颜色控件添加进面板并返回面板对象。

2.着色器材质
        它允许开发人员使用自定义的着色器进行渲染。通过该材质可以开发出很多酷炫的特效,对画面的提升有巨大作用。

        示例中创建着色器材质,将着色器材质应用到圆环结网格对象,具体代码如下所示:

1     var createScene = function() {                       //创建场景的函数2         var scene = new BABYLON.Scene(engine);          //创建场景3               var camera = new BABYLON.ArcRotateCamera("Camera",4              0, Math.PI / 2, 12, BABYLON.Vector3.Zero(), scene); //创建弧度旋转摄像机5         camera.attachControl(canvas, false);             //设置摄像机的控制6         ......//此处省略顶点着色器和片元着色器的代码,它们将在下文进行详细介绍7         var shaderMaterial = new BABYLON.ShaderMaterial("shader", scene, {//创建着色器材质8              vertex: "custom",                            //着色器传入方式9              fragment: "custom", }, {10                 attributes: ["position", "normal"],     //attribute变量11                 uniforms: ["world", "worldView", "worldViewProjection", "view","projection"]});12        var refTexture = new BABYLON.Texture("textures/ref.jpg", scene);//加载计算所需纹理13        refTexture.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;  //设置 U轴纹理拉伸方式14        refTexture.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;  //设置 V轴纹理拉伸方式15        shaderMaterial.setTexture("refSampler", refTexture);   //将纹理送入着色器16        shaderMaterial.backFaceCulling = false;                 //材质关闭背面剪裁17        var mesh = BABYLON.Mesh.CreateTorusKnot("mesh", 2, 0.5, 128, 64, 2, 3, scene);//创建圆环结18        mesh.material = shaderMaterial;                 //将圆环结的材质设置为着色器材质19        var angle=0;                                     //旋转角度20        scene.onBeforeRenderObservable.add(()=>{       //渲染之前对应的函数21             angle=angle+0.01;                           //增加旋转角度22             mesh.rotation.set(0, angle,0);               //修改圆环结的旋转角度23        })24        return scene;                                    //返回场景25    }

        此段代码的作用主要是创建场景和弧度旋转摄像机,然后创建着色器材质,并且指定着色器传入方式,传入attribute变量和uniform变量。然后加载纹理,设置纹理UV轴的拉伸方式,关闭背面剪裁并将纹理送入GPU管线。最后将圆环结的材质设置为着色器材质,并不断旋转圆环结。本案例采用了加载程序中着色器字符串的方法,读者可以自行体验其他两种着色器加载方式。
        示例中着色器代码的开发,包括顶点着色器和片元着色器。着色器代码具体如下所示:

 1     BABYLON.Effect.ShadersStore["customVertexShader"]= //顶点着色器2     "in vec3 position; \r\n"+                            //顶点坐标3     "in vec3 normal; \r\n"+                              //顶点法向量4     "uniform mat4 worldViewProjection; \r\n"+            //总变换矩阵5     "out vec4 vPosition; \r\n"+                          //输出片元着色器的顶点坐标6     "out vec3 vNormal; \r\n"+                            //输出片元着色器的法向量7     "void main() {\r\n"+8     "    vec4 p = vec4( position, 1. ); \r\n"+          //顶点坐标9     "    vPosition = p; \r\n"+                           //顶点坐标传递给片元着色器10    "    vNormal = normal; \r\n"+                        //法向量传递给片元着色器11    "    gl_Position = worldViewProjection * p; \r\n"+  //根据总变换矩阵计算此次绘制的顶点位置12    "}\r\n";13    BABYLON.Effect.ShadersStore["customFragmentShader"]=  //片元着色器14    "precision highp float; \r\n"+                          //浮点数精度15    "uniform mat4 worldView; \r\n"+                         //视图矩阵16    "in vec4 vPosition; \r\n"+                              //从顶点着色器接收的顶点坐标17    "in vec3 vNormal; \r\n"+                                //从顶点着色器接收的法向量18    "uniform sampler2D refSampler; \r\n"+                   //纹理数据19    "void main() {\r\n"+20    "    vec3 e = normalize( vec3( worldView * vPosition ) ); \r\n"+    //将顶点坐标变换至相机坐标系下并单位化21    "    vec3 n = normalize( worldView * vec4(vNormal, 0.0) ).xyz; \r\n"+//将法向量变换至相机坐标系下并单位化22    "    vec3 r = reflect( e, n ); \r\n"+                   //求反射向量23    "    float m = 2. * sqrt(\r\n"+                   //求球形纹理的反射向量长度24    "        pow( r.x, 2. ) +\r\n"+25    "        pow( r.y, 2. ) +\r\n"+26    "        pow( r.z + 1., 2. )\r\n"+27    "    ); \r\n"+28    "    vec2 vN = r.xy / m + .5; \r\n"+         //单位化纹理的反射向量 xy坐标并右移0.529    "    vec3 base = texture2D( refSampler, vN).rgb; \r\n"+  //纹理采样30    "    glFragColor = vec4( base, 1. ); \r\n"+               //输出到片元的颜色31    "}\r\n";

        ❑ 第1~12行为此程序的顶点着色器。其功能是根据总变换矩阵计算出每次绘制的顶点位置,并将顶点坐标和顶点法向量传递给片元着色器。
        ❑ 第13~31行为此程序的片元着色器。其功能是将顶点坐标和顶点法向量变化到摄像机坐标系,并求出顶点的反射向量,然后求出球形纹理上对应的反射向量,并计算出球形纹理的采样坐标,最后将纹理采样的颜色输出到片元。
 

http://www.xdnf.cn/news/978499.html

相关文章:

  • 【Chipyard】 conda 环境安装与使用
  • k8s在节点上加污点
  • k8s 部署服务常见错误原因
  • Windows 安装 Maven
  • 1Panel 部署 OpenResty + Redis 实现 IP 动态封禁教程
  • 软考 系统架构设计师系列知识点之杂项集萃(87)
  • Visual Studio 2022 运行提示:未在本地计算机上注册“Microsoft.Jet.OLEDB.4.0”提供程序。
  • jsoncpp ubuntu编译问题
  • Proof of Talk专访CertiK联创顾荣辉:全周期安全方案护航Web3生态
  • Cilium动手实验室: 精通之旅---22.Cilium Traffic Optimization
  • OA协同平台有哪些功能?OA协同办公软件平台如何选择?
  • 腾讯开源 ovCompose 跨平台框架:实现一次跨三端(Android/iOS/鸿蒙)
  • 网络请求与本地存储:Axios 与 AsyncStorage 在 React Native 中的应用
  • 升级 Ubuntu Linux 内核的几种不同方法
  • 同步与异步:软件工程中的时空艺术与实践智慧-以蜻蜓hr人才系统举例-优雅草卓伊凡
  • 二刷苍穹外卖 day02
  • 2023蓝桥杯C/C++ B组国赛
  • PyTorch:让深度学习飞入寻常百姓家(从零开始玩转张量与神经网络!)
  • 开疆智能ModbusTCP转Canopen网关连接汇川PLC配置案例
  • 【android bluetooth 框架分析 04】【bt-framework 层详解 4】【AdapterState介绍】
  • 25-Oracle 23ai DBMS_SEARCH — Ubiquitous Search(无处不在的搜索)
  • Qt Connections详解:信号与槽的核心机制
  • spring boot2 +java-jwt轻量实现jwt
  • AI中间件,构建大模型应用的标准化接入枢纽
  • 文献管理软件EndNote下载与安装教程(详细教程)2025最新版详细图文安装教程
  • 2025年- H80-Lc188--198.打家劫舍(动态规划)--Java版
  • 前端基础知识ES6系列 - 03(数组新增了哪些扩展)
  • SCADA|信创KingSCADA4.0与KingSCADA3.8的几点不同
  • 基于微信小程序的天气预报app
  • 一键批量修改XML标签名称:告别手工修改,高效管理标注数据