赞
踩
ArcGIS Maps SDK for JavaScript 从 4.29
开始增加 RenderNode
类,可以添加数据以及操作 FBO(ManagedFBO)
;
通过操作 FBO,可以通过后处理实现很多效果,官方提供了几个示例,感兴趣可以看看。
本文介绍一下通过 FBO,添加自定义数据。
本文包括核心代码、完整代码以及在线示例。
原理就是将坐标数据转为 WebGL 内部数据,即世界坐标;
在通过相机对象属性,传入投影矩阵与视图矩阵;
通过相机矩阵转换世界坐标,显示在地图上。
// 初始化shader var VSHADER = `#version 300 es layout (location=0) in vec3 a_Position; layout (location=1) in vec4 a_color; out vec4 v_color; uniform mat4 u_projectionMatrix; uniform mat4 u_viewMatrix; void main(){ gl_Position = u_projectionMatrix*u_viewMatrix*vec4(a_Position,1.0); // 传递颜色 v_color = a_color; } `; var FSHADER = `#version 300 es precision mediump float; in vec4 v_color; out vec4 fragColor; void main(){ fragColor = vec4(v_color.rgb*2.0,0.5); } `;
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"/> <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no"/> <title>自定义三角形 | Sample | ArcGIS Maps SDK for JavaScript 4.29</title> <link rel="stylesheet" href="./4.29/esri/themes/light/main.css"/> <script src="./4.29/init.js"></script> <script src="./renderCommon.js"></script> <style> html, body, #viewDiv { padding: 0; margin: 0; height: 100%; width: 100%; } </style> <script> require([ "esri/core/Accessor", "esri/Map", "esri/views/SceneView", "esri/views/3d/externalRenderers", "esri/geometry/Extent", "esri/rest/query", "esri/rest/support/Query", "esri/widgets/Home", "esri/core/promiseUtils", "esri/views/3d/webgl/RenderNode", "esri/views/3d/webgl", "esri/geometry/SpatialReference", ], (Accessor, Map, SceneView, externalRenderers, Extent, query, Query, Home, promiseUtils, RenderNode, webgl, SpatialReference, ) => { const {map, view} = initMap({Map, SceneView, Home}); // 创建三角形数据 // 经纬度 let projectionCoordinates = [ // lon lat elevation 115.12, 32, 0, 120, 31, 0, 124, 33, 0 ]; // 创建三角形颜色 let colors = new Float32Array( [ 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0 ] ) // Derive a new subclass from RenderNode called LuminanceRenderNode const TriAngleRenderNode = RenderNode.createSubclass({ constructor: function () { // consumes and produces define the location of the the render node in the render pipeline this.consumes = {required: ["composite-color"]}; this.produces = "composite-color"; }, // Ensure resources are cleaned up when render node is removed destroy() { this.shaderProgram && this.gl?.deleteProgram(this.shaderProgram); this.vbo && this.gl?.deleteBuffer(this.vbo); this.colorBuffer && this.gl?.deleteBuffer(this.colorBuffer); }, properties: {}, initialize: function () { let gl = this.gl; // 初始化shader var VSHADER = `#version 300 es layout (location=0) in vec3 a_Position; layout (location=1) in vec4 a_color; out vec4 v_color; uniform mat4 u_projectionMatrix; uniform mat4 u_viewMatrix; void main(){ gl_Position = u_projectionMatrix*u_viewMatrix*vec4(a_Position,1.0); // 传递颜色 v_color = a_color; } `; var FSHADER = `#version 300 es precision mediump float; in vec4 v_color; out vec4 fragColor; void main(){ fragColor = vec4(v_color.rgb*2.0,0.5); } `; // 初始化 shader 程序 this.shaderProgram = initWebgl2Shaders(gl, VSHADER, FSHADER); if (!this.shaderProgram) { console.assert("初始化shader错误") } // 获取顶点位置 this.a_Position = gl.getAttribLocation(this.shaderProgram, 'a_Position') // 获取顶点颜色 this.a_color = gl.getAttribLocation(this.shaderProgram, 'a_color') // 初始化顶点的 bufferdata this.vbo = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo); // 转换坐标为渲染坐标 let renderCoordinates = webgl.toRenderCoordinates( view, // 经纬度坐标 projectionCoordinates, // 开始索引 0, // 坐标系 SpatialReference.WGS84, // 顶点容器 new Float32Array(9), // 目标开始索引 0, // 顶点数量 3 ); gl.bufferData(gl.ARRAY_BUFFER, renderCoordinates, gl.STATIC_DRAW); // 给顶点的各个点赋予颜色 this.colorBuffer = gl.createBuffer() //创建缓冲区对象 gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer) //将缓冲区对象绑定到目标 gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW) //向缓冲区对象写入数据 }, // 渲染 render: function (inputs) { // The field input contains all available framebuffer objects // We need color texture from the composite render target this.resetWebGLState(); // 获取输出 FBO const output = this.bindRenderTarget(); let gl = this.gl; // 开启透明 activeOpacity(gl); gl.useProgram(this.shaderProgram); // 使用 shader 程序 gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo); gl.vertexAttribPointer(this.a_Position, 3, gl.FLOAT, false, 0, 0) //将缓冲区对象分配给a_Posiotion gl.enableVertexAttribArray(this.a_Position); // 启用 a_Position gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer) //将缓冲区对象绑定到目标 gl.vertexAttribPointer(this.a_color, 3, gl.FLOAT, false, 0, 0) //将缓冲区对象分配给a_color gl.enableVertexAttribArray(this.a_color); // 开启相机投影 activeMatrix(this) gl.drawArrays(gl.TRIANGLES, 0, 3); // 绘制图形 return output; }, a_Position: undefined, // 顶点位置 a_color: undefined, // 顶点颜色 vbo: undefined, // 顶点缓冲区对象 colorBuffer: undefined, // 颜色缓冲区对象 shaderProgram: null, // shader 程序 }); promiseUtils .eachAlways([view.when()]) .then((results) => { // Initializes the new custom render node and connects to SceneView const triAngleRenderNode = new TriAngleRenderNode({view}); }) }); </script> </head> <body> <div id="viewDiv"></div> </body> </html>
ArcGIS Maps SDK for JavaScript 在线示例:添加自定义(GLSL)数据
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。