WebGL简易教程(九):综合实例:地形的绘制

更新时间:2023-06-08 22:32:32 阅读: 评论:0

WebGL简易教程(九):综合实例:地形的绘制
⽬录
1. 概述
在上⼀篇教程中,给三维场景加⼊了简单的交互,通过⿏标实现场景的旋转和缩放。那么在这⼀篇教程中,综合前⾯的知识,可以做出⼀个稍微复杂的实例:绘制⼀张基于现实的地形图。
地形也就是DEM(数字⾼程模型),是由⼀组⽹格点组成的模型,每个点都有x,y,z值;更简单来说,图像格式就可以作为DEM的载体,只不过每个图像的像素值代表的是⾼程的值。这⾥准备了⼀张tif格式的DEM数据DEM.tif:
这张tif是从⾕歌地球上下载下来的,是美国⼤峡⾕的某⼀块地形。因为JS处理tif稍微有点⿇烦,我这⾥预先将其处理成DEM.dem,这是⼀个⽂本格式:
其中第⼀⾏的六个值分别表⽰:
起点X坐标起点Y坐标 X间距 Y间距宽⾼
剩下的每⼀⾏表⽰⼀个点,点的顺序为从上⾄下,从左⾄右:
与起点X距离与起点Y距离⾼程值颜⾊R 颜⾊G 颜⾊B 法向量X坐标法向量Y坐标法向量Z坐标
⼀般来说DEM⾥⾯保存的应该只有点的位置信息也就是XYZ坐标,其渲染的颜⾊信息和法向量信息是预处理的过程中计算出来的。⽬前来说可以将其当成已知量,以后有机会将会在后续介绍详细的预处理过程。
2. 实例
2.1. TerrainViewer.html
<!DOCTYPE html>
<html>
<head>
护肤品顺序<meta chart="utf-8" />
<title> 显⽰地形 </title>
<title>Hello Triangle</title>
</head>
<body onload="main()">
<div><input type='file' id='demFile'></div>
<div>
<canvas id="webgl" width="600" height="600">
请使⽤⽀持WebGL的浏览器
</canvas>
</div>
<script src="../lib/webgl-utils.js"></script>
<script src="../lib/webgl-debug.js"></script>
营养早餐吃什么<script src="../lib/cuon-utils.js"></script>
<script src="../lib/cuon-matrix.js"></script>
<script src="TerrainViewer.js"></script>
</body>
</html>
在HTML的代码中,添加了⼀个input按钮元素,⽤来导⼊DEM⽂件。⼀旦加载成功,canvas元素就会把读取的数据显⽰出来。
2.2. TerrainViewer.js
// 顶点着⾊器程序
var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +  //位置
'attribute vec4 a_Color;\n' + //颜⾊
'uniform mat4 u_MvpMatrix;\n' +
'varying vec4 v_Color;\n' +
'void main() {\n' +
'  gl_Position = u_MvpMatrix * a_Position;\n' + // 设置顶点坐标
'  v_Color = a_Color;\n' +
'}\n';
// ⽚元着⾊器程序
var FSHADER_SOURCE =
'precision mediump float;\n' +
'varying vec4 v_Color;\n' +气管炎都有哪些症状
'void main() {\n' +
'  gl_FragColor = v_Color;\n' +
'}\n';
//定义⼀个矩形体:混合构造函数原型模式
function Cuboid(minX, maxX, minY, maxY, minZ, maxZ) {
this.minX = minX;
this.maxX = maxX;
this.minY = minY;
this.maxY = maxY;
this.minZ = minZ;
this.maxZ = maxZ;
}
Cuboid.prototype = {
constructor: Cuboid,
CenterX: function () {
return (this.minX + this.maxX) / 2.0;
},
CenterY: function () {
return (this.minY + this.maxY) / 2.0;
},
CenterZ: function () {
return (this.minZ + this.maxZ) / 2.0;
},
LengthX: function () {
return (this.maxX - this.minX);
},
LengthY: function () {
return (this.maxY - this.minY);
}
}
/
/定义DEM
function Terrain() {
}
Terrain.prototype = {
constructor: Terrain,
tWH: function (col, row) {
}
}
var currentAngle = [0.0, 0.0]; // 绕X轴Y轴的旋转⾓度 ([x-axis, y-axis])
var curScale = 1.0;  //当前的缩放⽐例
function main() {
var demFile = ElementById('demFile');
if (!demFile) {
console.log("Failed to get demFile element!");
return;
}
//加载⽂件后的事件
demFile.addEventListener("change", function (event) {
//判断浏览器是否⽀持FileReader接⼝
if (typeof FileReader == 'undefined') {
console.log("你的浏览器不⽀持FileReader接⼝!");
return;
谜语大全简单}
//读取⽂件后的事件
var reader = new FileReader();
if (sult) {
var terrain = new Terrain();
if (!sult, terrain)) {
console.log("⽂件格式有误,不能读取该⽂件!");
}
/
/绘制函数
onDraw(gl, canvas, terrain);
}
}
var input = event.target;
});
// 获取 <canvas> 元素
var canvas = ElementById('webgl');
// 获取WebGL渲染上下⽂
var gl = getWebGLContext(canvas);
if (!gl) {
console.log('Failed to get the rendering context for WebGL');
return;
}
// 初始化着⾊器
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
console.log('Failed to intialize shaders.');
return;
}
// 指定清空<canvas>的颜⾊
gl.clearColor(0.0, 0.0, 0.0, 1.0);
/
/ 开启深度测试
//清空颜⾊和深度缓冲区
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
}
//绘制函数
function onDraw(gl, canvas, terrain) {
// 设置顶点位置
//var cuboid = new Cuboid(399589.072, 400469.072, 3995118.062, 3997558.062, 732, 1268);  var n = initVertexBuffers(gl, terrain);
if (n < 0) {
console.log('Failed to t the positions of the vertices');
return;
}
//注册⿏标事件
initEventHandlers(canvas);
//绘制函数
var tick = function () {
//设置MVP矩阵
彩色蚕宝宝tMVPMatrix(gl, canvas, terrain.cuboid);
//清空颜⾊和深度缓冲区
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
//绘制矩形体
gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_SHORT, 0);
//gl.drawArrays(gl.Points, 0, n);
//请求浏览器调⽤tick
requestAnimationFrame(tick);
};
//开始绘制
tick();
}
//读取DEM函数
function readDEMFile(result, terrain) {
var stringlines = result.split("\n");
if (!stringlines || stringlines.length <= 0) {
return fal;
}给父亲的生日礼物
//读取头信息
var subline = stringlines[0].split("\t");
if (subline.length != 6) {
return fal;
}
var col = parInt(subline[4]);      //DEM宽
var row = parInt(subline[5]);      //DEM⾼
var verticeNum = col * row;
if (verticeNum + 1 > stringlines.length) {
return fal;
}
terrain.tWH(col, row);
//读取点信息
var ci = 0;
terrain.verticesColors = new Float32Array(verticeNum * 6);
for (var i = 1; i < stringlines.length; i++) {
if (!stringlines[i]) {
continue;
}
var subline = stringlines[i].split(',');
if (subline.length != 9) {
continue;
}
for (var j = 0; j < 6; j++) {
terrain.verticesColors[ci] = parFloat(subline[j]);
ci++;
}
}
if (ci !== verticeNum * 6) {
return fal;
}
//包围盒
var minX = terrain.verticesColors[0];
var maxX = terrain.verticesColors[0];
var minY = terrain.verticesColors[1];
var maxY = terrain.verticesColors[1];
var minZ = terrain.verticesColors[2];
var maxZ = terrain.verticesColors[2];
for (var i = 0; i < verticeNum; i++) {
minX = Math.min(minX, terrain.verticesColors[i * 6]);
maxX = Math.max(maxX, terrain.verticesColors[i * 6]);
minY = Math.min(minY, terrain.verticesColors[i * 6 + 1]);
maxY = Math.max(maxY, terrain.verticesColors[i * 6 + 1]);
minZ = Math.min(minZ, terrain.verticesColors[i * 6 + 2]);
maxZ = Math.max(maxZ, terrain.verticesColors[i * 6 + 2]);
晚上口干舌燥}
terrain.cuboid = new Cuboid(minX, maxX, minY, maxY, minZ, maxZ);
给家捎个话return true;
}
//注册⿏标事件
function initEventHandlers(canvas) {
var dragging = fal;        // Dragging or not
var lastX = -1, lastY = -1;  // Last position of the mou
//⿏标按下
var x = ev.clientX;
var y = ev.clientY;
// Start dragging if a moue is in <canvas>
var rect = BoundingClientRect();
if (rect.left <= x && x < rect.right && p <= y && y < rect.bottom) {      lastX = x;
lastY = y;
dragging = true;
}
};

本文发布于:2023-06-08 22:32:32,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/89/1027043.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:坐标   绘制   信息   深度   读取
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图