基於 HTML5 WebGL 的 3D 場景中的燈光效果
前言
構建 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);
總結
整個例子結束,感覺就是“小程式碼大效果”,程式碼量少而且簡單,效果又非常不錯,大家有興趣可以去官網或者手冊中檢視其它的例子。
相關文章
- 基於 HTML5 WebGL 構建智慧城市 3D 場景HTMLWeb3D
- 基於WebGL HTML5 的場景小遊戲WebHTML遊戲
- 基於 HTML5 + WebGL 的 3D 風力發電場HTMLWeb3D
- 基於 HTML5 WebGL 的 3D 機房HTMLWeb3D
- 基於 HTML5 WebGL 的 3D 挖掘機HTMLWeb3D
- 基於 HTML5 的 WebGL 3D 隧道監控HTMLWeb3D
- 基於 HTML5 WebGL 的 3D 科幻風機HTMLWeb3D
- 基於 HTML5 WebGL 的 3D 工控裙房系統HTMLWeb3D
- 基於 HTML5 WebGL 的 3D 模型斜面生成HTMLWeb3D模型
- 基於 WebGL HTML5 的 3D 模型分離控制WebHTML3D模型
- 基於 WebGL 的 HTML5 3D 工控裙房系統WebHTML3D
- 基於 WebGl HTML5 的 3D 視覺化機房WebHTML3D視覺化
- 基於 HTML5 WebGL 的 3D 網路拓撲圖HTMLWeb3D
- 基於 WebGL 的 HTML5 3D SCADA 主站系統WebHTML3D
- 基於 WebGL 的 HTML5 3D 網路拓撲圖WebHTML3D
- 基於 HTML5 + WebGL 的 3D 風力發電場視覺化系統HTMLWeb3D視覺化
- 基於 HTML5 WebGL 的 3D 棉花加工監控系統HTMLWeb3D
- 基於 HTML5 + WebGL 的太陽系 3D 展示系統HTMLWeb3D
- 基於 WebGL 實現的 HTML5 3D “彈力”佈局WebHTML3D
- 基於 HTML5 WebGL 實現的 3D “彈力”佈局HTMLWeb3D
- 基於 WebGL 的 HTML5 3D 棉花加工監控系統WebHTML3D
- 基於HTML5 WebGL的工業化3D電子圍欄HTMLWeb3D
- 基於 HTML5 WebGL 的 3D 風機視覺化系統HTMLWeb3D視覺化
- 基於 WebGL 的 HTML5 3D 智慧樓宇監控系統WebHTML3D
- 基於 WebGL 的 HTML5 網路拓撲結構 3D 圖WebHTML3D
- 基於 WebGL 的 HTML5 3D 工控隧道視覺化系統WebHTML3D視覺化
- 基於 HTML5 WebGL 的挖掘機 3D 視覺化應用HTMLWeb3D視覺化
- 基於 HTML5 的 WebGL 3D 智慧樓宇監控系統HTMLWeb3D
- 基於 HTML5 WebGL 的智慧城市(一)HTMLWeb
- 基於 HTML5 Canvas 的 3D 熱力雲圖效果HTMLCanvas3D
- 基於 HTML5 的 WebGL 樓宇自控 3D 視覺化監控HTMLWeb3D視覺化
- 基於 HTML5 的 WebGL 3D 地鐵站視覺化系統HTMLWeb3D視覺化
- 基於 WebGL 的 HTML5 樓宇自控 3D 視覺化監控WebHTML3D視覺化
- 基於 HTML5 的 WebGL 自定義 3D 攝像頭監控模型HTMLWeb3D模型
- 基於 HTML5 WebGL 的加油站 3D 視覺化監控HTMLWeb3D視覺化
- 基於 HTML5 + WebGL 的無人機 3D 視覺化系統HTMLWeb無人機3D視覺化
- 基於 HTML5 + WebGL 的太陽系 3D 視覺化系統HTMLWeb3D視覺化
- 基於 HTML5 WebGL 的發動機 3D 視覺化系統HTMLWeb3D視覺化