WebGL的颜色渲染-渲染一张DEM(数字高程模型)

WebGL的颜色渲染-渲染一张DEM(数字高程模型),第1张

概述目录 1. 具体实例 2. 解决方案 1) DEM数据.XYZ文件 2) showDEM.html 3) showDEM.js 4) 运行结果 3. 详细讲解 1) 读取文件 2) 绘制函数 3) 使用缓冲区对象 4. 其他 1. 具体实例 通过WebGL,可以渲染生成DEM(数字高程模型)。DEM(数字高程模型)是网格点组成的模型,每个点都有x,y,z值;x,y根据一定的间距组成网格状,同时根据

目录

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的渲染效果:

3. 详细讲解 1) 读取文件

程序的第一步是通过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(数字高程模型)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1086125.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-27
下一篇 2022-05-27

发表评论

登录后才能评论

评论列表(0条)

保存