目录
1. 具体实例 2. 解决方案 1) DEM数据.XYZ文件 2) showDEM.html 3) showDEM.js 4) 运行结果 3. 详细讲解 1) 读取文件 2) 绘制函数 3) 使用缓冲区对象 @L_404_10@ 1. 具体实例通过WebGL,可以渲染生成DEM(数字高程模型)。DEM(数字高程模型)是网格点组成的模型,每个点都有x,y,z值;x,y根据一定的间距组成网格状,同时根据z值的高低来选定每个点的颜色RGB。通过这个例子可以熟悉WebGL颜色渲染的过程。
2. 解决方案 1) DEM数据.XYZ文件这里使用的DEM文件的数据组织如下,如下图所示。
其中每一行表示一个点,前三个数值表示位置XYZ,后三个数值表示颜色RGB。 2) showDEM.HTML
<!DOCTYPE HTML><HTML><head> <Meta charset="UTF-8"> <Title> 显示地形 </Title> <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="showDEM.Js"></script></head><body> <div><input type = 'file' ID = 'demfile' ></div> <!-- <div><textarea ID="output" rows="300" cols="200"></textarea></div> --> <div> <canvas ID ="demCanvas" wIDth="600" height="600"> 请使用支持WebGL的浏览器 </canvas> </div></body></HTML>3) showDEM.Js
// Vertex shader programvar VSHADER_SOURCE = //'precision highp float;\n' + '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';// Fragment shader programvar FSHADER_SOURCE = '#ifdef GL_ES\n' + 'precision mediump float;\n' + '#endif\n' + 'varying vec4 v_color;\n' + 'voID main() {\n' + ' gl_Fragcolor = v_color;\n' + '}\n';//var col = 89; //DEM宽var row = 245; //DEM高// Current rotation angle ([x-axis,y-axis] degrees)var currentAngle = [0.0,0.0];//当前lookAt()函数初始视点的高度var eyeHight = 2000.0;//setPerspective()远截面var far = 3000;//window.onload = function () { var demfile = document.getElementByID('demfile'); if (!demfile) { console.log("Error!"); return; } //demfile.onchange = openfile(event); demfile.addEventListener("change",function (event) { //判断浏览器是否支持fileReader接口 if (typeof fileReader == 'undefined') { console.log("你的浏览器不支持fileReader接口!"); return; } // var reader = new fileReader(); reader.onload = function () { if (reader.result) { // var stringlines = reader.result.split("\n"); verticescolors = new float32Array(stringlines.length * 6); // var pn = 0; var ci = 0; for (var i = 0; i < stringlines.length; i++) { if (!stringlines[i]) { continue; } var subline = stringlines[i].split(','); if (subline.length != 6) { console.log("错误的文件格式!"); return; } for (var j = 0; j < subline.length; j++) { verticescolors[ci] = parsefloat(subline[j]); ci++; } pn++; } if (ci < 3) { console.log("错误的文件格式!"); } // var minX = verticescolors[0]; var maxX = verticescolors[0]; var minY = verticescolors[1]; var maxY = verticescolors[1]; var minZ = verticescolors[2]; var maxZ = verticescolors[2]; for (var i = 0; i < pn; i++) { minX = Math.min(minX,verticescolors[i * 6]); maxX = Math.max(maxX,verticescolors[i * 6]); minY = Math.min(minY,verticescolors[i * 6 + 1]); maxY = Math.max(maxY,verticescolors[i * 6 + 1]); minZ = Math.min(minZ,verticescolors[i * 6 + 2]); maxZ = Math.max(maxZ,verticescolors[i * 6 + 2]); } //包围盒中心 var cx = (minX + maxX) / 2.0; var cy = (minY + maxY) / 2.0; var cz = (minZ + maxZ) / 2.0; //根据视点高度算出setPerspective()函数的合理角度 var fovy = (maxY - minY) / 2.0 / eyeHight; fovy = 180.0 / Math.PI * Math.atan(fovy) * 2; startDraw(verticescolors,cx,cy,cz,fovy); } }; // var input = event.target; reader.readAsText(input.files[0]); });}function startDraw(verticescolors,fovy) { // RetrIEve <canvas> element var canvas = document.getElementByID('demCanvas'); // Get the rendering context for WebGL var gl = getWebGLContext(canvas); if (!gl) { console.log('Failed to get the rendering context for WebGL'); return; } // Initialize shaders if (!initShaders(gl,VSHADER_SOURCE,FSHADER_SOURCE)) { console.log('Failed to intialize shaders.'); return; } // Set the vertex coordinates and color (the blue triangle is in the front) n = initVertexBuffers(gl,verticescolors); //,verticescolors,n if (n < 0) { console.log('Failed to set the vertex information'); return; } // Get the storage location of u_MvpMatrix var u_MvpMatrix = gl.getUniformlocation(gl.program,'u_MvpMatrix'); if (!u_MvpMatrix) { console.log('Failed to get the storage location of u_MvpMatrix'); return; } // Register the event handler initEventHandlers(canvas); // Specify the color for clearing <canvas> gl.clearcolor(0,1); gl.enable(gl.DEPTH_TEST); // Start drawing var tick = function () { //setPerspective()宽高比 var aspect = canvas.wIDth / canvas.height; // draw(gl,n,aspect,fovy,u_MvpMatrix); requestAnimationFrame(tick,canvas); }; tick();}//function initEventHandlers(canvas) { var dragging = false; // Dragging or not var lastX = -1,lastY = -1; // Last position of the mouse // Mouse is pressed canvas.onmousedown = function (ev) { var x = ev.clIEntX; var y = ev.clIEntY; // Start dragging if a moue is in <canvas> var rect = ev.target.getBoundingClIEntRect(); if (rect.left <= x && x < rect.right && rect.top <= y && y < rect.bottom) { lastX = x; lastY = y; dragging = true; } }; //鼠标离开时 canvas.onmouseleave = function (ev) { dragging = false; }; // Mouse is released canvas.onmouseup = function (ev) { dragging = false; }; // Mouse is moved canvas.onmousemove = function (ev) { var x = ev.clIEntX; var y = ev.clIEntY; if (dragging) { var factor = 100 / canvas.height; // The rotation ratio var dx = factor * (x - lastX); var dy = factor * (y - lastY); // limit x-axis rotation angle to -90 to 90 degrees //currentAngle[0] = Math.max(Math.min(currentAngle[0] + dy,90.0),-90.0); currentAngle[0] = currentAngle[0] + dy; currentAngle[1] = currentAngle[1] + dx; } lastX = x,lastY = y; }; //鼠标缩放 canvas.onmousewheel = function (event) { var lastHeight = eyeHight; if (event.wheelDelta > 0) { eyeHight = Math.max(1,eyeHight - 80); } else { eyeHight = eyeHight + 80; } far = far + eyeHight - lastHeight; };}function draw(gl,u_MvpMatrix) { //模型矩阵 var modelMatrix = new Matrix4(); modelMatrix.rotate(currentAngle[0],1.0,0.0,0.0); // Rotation around x-axis modelMatrix.rotate(currentAngle[1],0.0); // Rotation around y-axis modelMatrix.translate(-cx,-cy,-cz); //视图矩阵 var vIEwMatrix = new Matrix4(); vIEwMatrix.lookAt(0,eyeHight,1,0); //投影矩阵 var projMatrix = new Matrix4(); projMatrix.setPerspective(fovy,10,far); //模型视图投影矩阵 var mvpMatrix = new Matrix4(); mvpMatrix.set(projMatrix).multiply(vIEwMatrix).multiply(modelMatrix); // Pass the model vIEw projection matrix to u_MvpMatrix gl.uniformMatrix4fv(u_MvpMatrix,false,mvpMatrix.elements); // Clear color and depth buffer gl.clear(gl.color_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); // Draw the cube gl.drawElements(gl.TRIANGLES,gl.UNSIGNED_SHORT,0);}function initVertexBuffers(gl,verticescolors) { //DEM的一个网格是由两个三角形组成的 // 0------1 1 // | | // | | // col col------col+1 var indices = new Uint16Array((row - 1) * (col - 1) * 6); var ci = 0; for (var yi = 0; yi < row - 1; yi++) { for (var xi = 0; xi < col - 1; xi++) { indices[ci * 6] = yi * col + xi; indices[ci * 6 + 1] = (yi + 1) * col + xi; indices[ci * 6 + 2] = yi * col + xi + 1; indices[ci * 6 + 3] = (yi + 1) * col + xi; indices[ci * 6 + 4] = (yi + 1) * col + xi + 1; indices[ci * 6 + 5] = yi * col + xi + 1; ci++; } } //创建缓冲区对象 var vertexcolorBuffer = gl.createBuffer(); var indexBuffer = gl.createBuffer(); if (!vertexcolorBuffer || !indexBuffer) { return -1; } // 将缓冲区对象绑定到目标 gl.bindBuffer(gl.ARRAY_BUFFER,vertexcolorBuffer); // 向缓冲区对象中写入数据 gl.bufferData(gl.ARRAY_BUFFER,gl.STATIC_DRAW); // var FSIZE = verticescolors.BYTES_PER_ELEMENT; // 向缓冲区对象分配a_position变量 var a_position = gl.getAttribLocation(gl.program,'a_position'); if (a_position < 0) { console.log('Failed to get the storage location of a_position'); return -1; } gl.vertexAttribPointer(a_position,3,gl.float,FSIZE * 6,0); //开启a_position变量 gl.enabLevertexAttribarray(a_position); // 向缓冲区对象分配a_color变量 var a_color = gl.getAttribLocation(gl.program,'a_color'); if (a_color < 0) { console.log('Failed to get the storage location of a_color'); return -1; } gl.vertexAttribPointer(a_color,FSIZE * 3); //开启a_color变量 gl.enabLevertexAttribarray(a_color); // 写入并绑定顶点数组的索引值 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indexBuffer); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,indices,gl.STATIC_DRAW); return indices.length;}4) 运行结果
用Chrome打开showDEM.HTML,选择DEM文件,界面就会显示DEM的渲染效果:
程序的第一步是通过Js的fileReader()函数读取DEM文件,在其回调函数中读取到数组verticescolors中,它包含了位置和颜色信息。读取完成后调用绘制函数startDraw()。
//var reader = new fileReader();reader.onload = function () { if (reader.result) { // var stringlines = reader.result.split("\n"); verticescolors = new float32Array(stringlines.length * 6); // var pn = 0; var ci = 0; for (var i = 0; i < stringlines.length; i++) { if (!stringlines[i]) { continue; } var subline = stringlines[i].split(','); if (subline.length != 6) { console.log("错误的文件格式!"); return; } for (var j = 0; j < subline.length; j++) { verticescolors[ci] = parsefloat(subline[j]); ci++; } pn++; } if (ci < 3) { console.log("错误的文件格式!"); } // var minX = verticescolors[0]; var maxX = verticescolors[0]; var minY = verticescolors[1]; var maxY = verticescolors[1]; var minZ = verticescolors[2]; var maxZ = verticescolors[2]; for (var i = 0; i < pn; i++) { minX = Math.min(minX,verticescolors[i * 6]); maxX = Math.max(maxX,verticescolors[i * 6]); minY = Math.min(minY,verticescolors[i * 6 + 1]); maxY = Math.max(maxY,verticescolors[i * 6 + 1]); minZ = Math.min(minZ,verticescolors[i * 6 + 2]); maxZ = Math.max(maxZ,verticescolors[i * 6 + 2]); } //包围盒中心 var cx = (minX + maxX) / 2.0; var cy = (minY + maxY) / 2.0; var cz = (minZ + maxZ) / 2.0; //根据视点高度算出setPerspective()函数的合理角度 var fovy = (maxY - minY) / 2.0 / eyeHight; fovy = 180.0 / Math.PI * Math.atan(fovy) * 2; startDraw(verticescolors,fovy); }};//var input = event.target;reader.readAsText(input.files[0]);2) 绘制函数
绘制DEM跟绘制一个简单三角形的步骤是差不多的:
获取WebGL环境。 初始化shaders,构建着色器。 初始化顶点数组,分配到缓冲对象。 绑定鼠标键盘事件,设置模型视图投影变换矩阵。 在重绘函数中调用WebGL函数绘制。其中最关键的步骤是第三步,初始化顶点数组initVertexBuffers()。
function startDraw(verticescolors,canvas); }; tick();}3) 使用缓冲区对象
在函数initVertexBuffers()中包含了使用缓冲区对象向顶点着色器传入多个顶点数据的过程:
创建缓冲区对象(gl.createBuffer()); 绑定缓冲区对象(gl.bindBuffer()); 将数据写入缓冲区对象(gl.bufferData); 将缓冲区对象分配给一个attribute变量(gl.vertexAttribPointer) 开启attribute变量(gl.enabLevertexAttribarray);在本例中,在Js中申请的数组verticescolors分成位置和颜色两部分分配给缓冲区对象,并传入顶点着色器;vertexAttribPointer()是其关键的函数,需要详细了解其参数的用法。最后,把顶点数据的索引值绑定到缓冲区对象,WebGL可以访问索引来间接访问顶点数据进行绘制。
function initVertexBuffers(gl,gl.STATIC_DRAW); return indices.length;}4. 其他
1.这里用到了几个《WebGL编程指南》书中提供的Js组件。全部源代码(包含DEM数据)地址链接:https://share.weiyun.com/5cvt8PJ ,密码:4aqs8e。
2.如果关心如何设置模型视图投影变换矩阵,以及绑定鼠标键盘事件,可参看这篇文章:WebGL或OpenGL关于模型视图投影变换的设置技巧。 3.渲染的结果如果加入光照,效果会更好。
以上是内存溢出为你收集整理的WebGL的颜色渲染-渲染一张DEM(数字高程模型)全部内容,希望文章能够帮你解决WebGL的颜色渲染-渲染一张DEM(数字高程模型)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)