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

基于 HTML5 WebGL 的 3D 场景中的灯光效果

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

前言

构建 3D 的场景除了创建模型,对模型设置颜色和贴图外,还需要有灯光的效果才能更逼真的反映真实世界的场景。这个例子我觉得既美观又代表性很强,所以拿出来给大家分享一下。

本例地址:http://www.hightopo.com/guide/guide/core/lighting/examples/example_flowing.html

例子动图:

图片描述

上面场景中主要的知识点包括:3D 灯光以及 3D 模型的流动。

1. 场景搭建

整个场景中包括 2D 场景(也就是鹰眼部分)以及 3D 场景:

dm = new ht.DataModel();
g3d = new ht.graph3d.Graph3dView(dm);
g3d.setGridVisible(true); // 指定是否显示网格
g3d.setGridColor('#74AADA'); // 指定网格线颜色
g3d.getView().className = 'main'; // 设置类名
document.body.appendChild(g3d.getView()); // 将3d组件添加进body体中
window.addEventListener('resize', function(e) {
    g3d.invalidate();
}, false);

g2d = new ht.graph.GraphView(dm);
g2d.setAutoScrollZone(-1); // 设置自动滚动区域大小,当鼠标距离拓扑边缘小于这个值时,拓扑自动滚动(调整translateX或translateY)
g2d.getView().className = 'g2d';
g2d.setEditable(true); // 设置拓扑中的图元是否可编辑
document.body.appendChild(g2d.getView());
ht.Default.callLater(g2d.fitContent, g2d, [true, 50, true]); // 获取全局下一个id编号

g3d.setHeadlightRange(2000); // 灯影响范围,默认为0代表可照射到无穷远处,如果设置了值则光照射效果随物体远离光影而衰减

所有HT组件最根层都为一个 div 组件,可通过组件的 getView() 函数获得,这里就是利用这种方法将 3D 和 2D 组件添加进 body 体中的。只要 3D 和 2D 共用同一个数据容器,那么数据容器中的图元都是共用的,也就是说只要我们排布好 2D 或者 3D 中的图元,那么剩下的那个组件中图元的排布以及样式都是根据排布好的组件来排布的。

2. 添加灯光

场景中出现的灯光,除了会旋转的灯光,还有就是两个静止的红灯和黄灯,当旋转的灯光照向其他地方的时候看得比较清楚:

redLight = new ht.Light(); // 灯类
redLight.p3(0, 0, -175); // 实例变量的位置
redLight.s({
    'light.color': 'red', // 灯光颜色
    'light.range': 400 // 灯影响范围,默认为0代表可照射到无穷远处,如果设置了值则光照射效果随物体远离光影而衰减
});
dm.add(redLight); // 将实例变量添加进数据容量中

rotateLight = new ht.Light();
rotateLight.s({
    'light.color': 'green',
    'light.type': 'spot' // 默认为point点光灯,可设置为spot聚光灯,以及directional的方向光类型
});
dm.add(rotateLight);

yellowLight = new ht.Light();
yellowLight.p3(0, 0, 60);
yellowLight.s({
    'light.color': 'yellow',
    'light.range': 200
});
dm.add(yellowLight);

3. 场景中模型的构建

首先是地板的创建,地板是一个圆形的地板,通过设置样式 shape3d 为 cylinder,剩下的只要设置好大小、位置以及样式等等即可:

floor = new ht.Node(); // Node 节点类
floor.s3(1100, 10, 1100);
floor.p3(0, -100, -110);
floor.s({
    'shape3d': 'cylinder', // 设置 3D 模型为圆形
    'shape3d.side': 100, // 默认值为0,决定3d图形显示为几边型,为0时显示为平滑的曲面效果
    'shape3d.color': 'white', // 默认值为#3498DB,3d图形整体颜色
    '3d.selectable': false, // 默认值为true,控制图元在Graph3dView上是否可选中
    '2d.visible': false // 默认值为true,控制图元在GraphView上是否可见
});
dm.add(floor);

接着添加地板外围的 8 根圆柱:

for(var i=0; i<8; i++){
    var angle = Math.PI*2*i/8;
          pillar = new ht.Node();
    pillar.s({
        'shape3d': 'cylinder',
         'shape3d.color': 'white',
         'shape': 'circle', // 多边形类型图元,为空时显示为图片
         'shape.background': 'gray' // 多边形类型图元背景
    });
    pillar.s3(50, 180, 50);
    pillar.p3(Math.cos(angle)*480, 0, -110+Math.sin(angle)*480);
    dm.add(pillar);
}

还有就是这些“箭头”作为贴图的模型,各种各样的,这里我就只解析一个,比较靠前的“波动”部分,具体的多边形的描述请参考形状手册:

图片描述

其中 image 的部分是通过 ht.Default.setImage 函数来创建的名为 arrow 的贴图。

shape3 = new ht.Shape(); // 多边形类
dm.add(shape3);
shape3.setTall(60); // 设置高度
shape3.setThickness(0); // 设置厚度
shape3.s({ // 设置样式
    'shape.background': null,
    'shape.border.width': 10, // 多边形类型图元边框宽度
    'shape.border.color': 'blue',

    'all.visible': false, // 六面是否可见
    'front.visible': true,
    'front.blend': 'blue', // 前面染色颜色
    'front.reverse.flip': true, // 前面的反面是否显示正面的内容
    'front.image': 'arrow', // 前面贴图
    'front.uv.scale': [16, 3] // 前面贴图的uv缩放,格式为[3,2]
});
shape3.setPoints([ // 设置点数组
    {x: 0, y: 0},
    {x: 25, y: -25},
    {x: 50, y: 0},
    {x: 75, y: 25},
    {x: 100, y: 0},
    {x: 125, y: -25},
    {x: 150, y: 0},
    {x: 175, y: 25},
    {x: 200, y: 0}
]);
shape3.setSegments([ // 描述点连接样式
    1, // moveTo
    3, // quadraticCurveTo
    3, // quadraticCurveTo
    3, // quadraticCurveTo
    3 // quadraticCurveTo
]);
shape3.p3(-100, 0, 100);
shape3.setRotationZ(-Math.PI/2); // 设置图元在3D拓扑中沿z轴的旋转角度(弧度制)

4. 设置定时器使各个模型中的图片“流动”以及旋转灯光的旋转

offset = 0;
angle = 0;
setInterval(function(){
    angle += Math.PI/50;
    rotateLight.p3(400*Math.cos(angle), 70, -110+400*Math.sin(angle)); // 设置旋转灯光的坐标

    offset += 0.1;
    uvOffset = [offset, 0];
    shape1.s({
        'front.uv.offset': uvOffset // 前面贴图的uv缩放,格式为[3,2]
    });
    shape2.s({
        'front.uv.offset': uvOffset
    });
    shape3.s({
        'front.uv.offset': uvOffset
    });
    shape4.s({
        'front.uv.offset': uvOffset
    });
    shape5.s({
        'shape3d.uv.offset': uvOffset, // 决定3d图形整体贴图的uv缩放,格式为[3,2]
        'shape3d.top.uv.offset': uvOffset, // 决定3d图形顶面贴图的uv缩放,格式为[3,2]
        'shape3d.bottom.uv.offset': uvOffset // 决定3d图形底面贴图的uv缩放,格式为[3,2]
    });
    cylinder.s({
        'shape3d.uv.offset': uvOffset
    });
    torus.s({
        'shape3d.uv.offset': uvOffset
    });
}, 200);

总结

整个例子结束,感觉就是“小代码大效果”,代码量少而且简单,效果又非常不错,大家有兴趣可以去官网或者手册中查看其它的例子。

转载于:https://my.oschina.net/xhload3d/blog/3058038

相关文章:

  • httptomcat
  • MySQL常用命令(转)
  • Head Html Css 第二版笔记
  • 比较快速排序,冒泡排序,双向冒泡排序的执行效率
  • 如何在vue-cli 3.x中使用jquery
  • Sentinel基本使用--熔断降级(基于RT, ExceptionRatio, ExceptionCount)
  • VTK学习笔记--4 数据集与数据属性
  • MYSQL一次千万级连表查询优化
  • Matlab中堆叠矩阵repmat的使用!
  • 人工智能又双叒“寒冬”了
  • LaTex 源码都在那
  • excel动态导入数据库---mysql
  • 还没被玩坏的robobrowser(5)——Beautiful Soup的过滤器
  • 基本概念---part4
  • 长春理工大学第十四届程序设计竞赛(重现赛)L.Homework Stream
  • php的引用
  • 10个最佳ES6特性 ES7与ES8的特性
  • 5分钟即可掌握的前端高效利器:JavaScript 策略模式
  • angular2开源库收集
  • ES6语法详解(一)
  • express.js的介绍及使用
  • FastReport在线报表设计器工作原理
  • Java 最常见的 200+ 面试题:面试必备
  • java8-模拟hadoop
  • JavaScript学习总结——原型
  • Koa2 之文件上传下载
  • k个最大的数及变种小结
  • Linux快速复制或删除大量小文件
  • log4j2输出到kafka
  • Spring思维导图,让Spring不再难懂(mvc篇)
  • vue中实现单选
  • 阿里云容器服务区块链解决方案全新升级 支持Hyperledger Fabric v1.1
  • 从零开始学习部署
  • 第2章 网络文档
  • 小试R空间处理新库sf
  • 协程
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • ​VRRP 虚拟路由冗余协议(华为)
  • ​插件化DPI在商用WIFI中的价值
  • # Pytorch 中可以直接调用的Loss Functions总结:
  • #define、const、typedef的差别
  • #if和#ifdef区别
  • #数学建模# 线性规划问题的Matlab求解
  • ${ }的特别功能
  • %3cli%3e连接html页面,html+canvas实现屏幕截取
  • (14)学习笔记:动手深度学习(Pytorch神经网络基础)
  • (3)选择元素——(14)接触DOM元素(Accessing DOM elements)
  • (Java实习生)每日10道面试题打卡——JavaWeb篇
  • (没学懂,待填坑)【动态规划】数位动态规划
  • (免费领源码)python#django#mysql校园校园宿舍管理系统84831-计算机毕业设计项目选题推荐
  • (推荐)叮当——中文语音对话机器人
  • (转)Java socket中关闭IO流后,发生什么事?(以关闭输出流为例) .
  • (转)winform之ListView
  • (转)从零实现3D图像引擎:(8)参数化直线与3D平面函数库
  • (转)关于多人操作数据的处理策略