当前位置:   article > 正文

Arcgis 进阶篇(3)——Arcgis js api的externalRenderers用法1_arcgis renderer

arcgis renderer

arcgis js api的externalRenderers可以直接使用webgl的shader,这样就使得你可以按照自己想法做各种效果。但前提是:熟悉webgl

1、externalRenderers简单使用

先看一下externalRenderers的介绍:

externalRenderers | API Reference | ArcGIS API for JavaScript 4.24 | ArcGIS DevelopersDocumentation site for ArcGIS API for JavaScript on ArcGIS Developers.https://developers.arcgis.com/javascript/latest/api-reference/esri-views-3d-externalRenderers.html这里的例子不是很清晰,以下是个简单的例子(在arcgis三维场景上画一个三角形):

  1. <template>
  2. <div id="main-view"></div>
  3. </template>
  4. <script>
  5. import SceneView from '@arcgis/core/views/SceneView'
  6. import Map from '@arcgis/core/Map'
  7. import esriConfig from "@arcgis/core/config";
  8. import * as externalRenderers from "@arcgis/core/views/3d/externalRenderers";
  9. import {initWebgl2Shaders} from '../utils/initWebgl2Shaders'
  10. import Matrix4 from '@math.gl/core/dist/es5/classes/matrix4'
  11. let viewer = null
  12. let map = null
  13. export default {
  14. mounted() {
  15. this.initConfig()
  16. this.init()
  17. this.initRender()
  18. },
  19. methods:{
  20. // 初始设置
  21. initConfig(){
  22. esriConfig.assetsPath = "./assets";
  23. },
  24. init(){
  25. map = new Map({
  26. basemap: 'hybrid',
  27. ground: "world-elevation"
  28. })
  29. viewer = new SceneView({
  30. map,
  31. container: 'main-view'
  32. })
  33. viewer.ui.empty('bottom-trailing')
  34. viewer.ui.empty('manual')
  35. },
  36. initRender(){
  37. let myExternalRenderer = {
  38. vbo: null,
  39. shaderProgram: null,
  40. a_Position: null,
  41. setup: function(context) {
  42. let gl = context.gl;
  43. // 初始化shader
  44. var VSHADER=`#version 300 es
  45. layout (location=0) in vec4 a_Position;
  46. void main(){
  47. gl_Position=a_Position;
  48. }
  49. `;
  50. var FSHADER=`#version 300 es
  51. precision mediump float;
  52. out vec4 fragColor;
  53. void main(){
  54. fragColor=vec4(1.0,0.0,0.0,1.0);
  55. }
  56. `;
  57. this.shaderProgram=initWebgl2Shaders(gl, VSHADER, FSHADER)
  58. if(!this.shaderProgram){
  59. console.assert("初始化shader错误")
  60. }
  61. this.a_Position= gl.getAttribLocation(this.shaderProgram, 'a_Position')
  62. gl.enableVertexAttribArray(this.a_Position) //连接变量a_Position和缓冲区对象
  63. // 初始化bufferdata
  64. this.vbo = context.gl.createBuffer();
  65. context.gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo);
  66. let positions = new Float32Array([0, 0, 0, 1, 0, 0, 0, 1, 0]);
  67. context.gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
  68. },
  69. render: function(context) {
  70. let gl = context.gl
  71. gl.enable(gl.DEPTH_TEST); // 开启深度检测
  72. // gl.disable(gl.CULL_FACE);
  73. // gl.disable(gl.BLEND);
  74. gl.useProgram(this.shaderProgram);
  75. // 创建数据
  76. context.gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo);
  77. gl.vertexAttribPointer(this.a_Position,3,gl.FLOAT,false,0,0) //将缓冲区对象分配给a_Posiotion
  78. context.gl.drawArrays(gl.TRIANGLES, 0, 3);
  79. console.log(1) // 每帧检测
  80. }
  81. }
  82. externalRenderers.add(viewer, myExternalRenderer);
  83. },
  84. }
  85. }
  86. </script>
  87. <style>
  88. #main-view{
  89. width: 1000px;
  90. height: 800px;
  91. }
  92. </style>

 其中initWebgl2Shaders的方法

  1. function checkShaderCompilation(gl, shader) {
  2. var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
  3. // console.log("Shader compiled successfully: " + compiled);
  4. var compilationLog = gl.getShaderInfoLog(shader);
  5. // console.log("Shader compiler log: " + compilationLog);
  6. }
  7. export function initWebgl2Shaders(gl, vertCode, fragCode) {
  8. // Create a vertex shader object
  9. var vertShader = gl.createShader(gl.VERTEX_SHADER);
  10. // Attach vertex shader source code
  11. gl.shaderSource(vertShader, vertCode);
  12. // Compile the vertex shader
  13. gl.compileShader(vertShader);
  14. checkShaderCompilation(gl, vertShader);
  15. // Create fragment shader object
  16. var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
  17. // Attach fragment shader source code
  18. gl.shaderSource(fragShader, fragCode);
  19. // Compile the fragment shader
  20. gl.compileShader(fragShader);
  21. checkShaderCompilation(gl, fragShader);
  22. // Create a shader program object to store
  23. // the combined shader program
  24. var shaderProgram = gl.createProgram();
  25. // Attach a vertex shader
  26. gl.attachShader(shaderProgram, vertShader);
  27. // Attach a fragment shader
  28. gl.attachShader(shaderProgram, fragShader);
  29. // Link both the programs
  30. gl.linkProgram(shaderProgram);
  31. // Use the combined shader program object
  32. gl.useProgram(shaderProgram);
  33. return shaderProgram;
  34. }

最终效果:

 2、添加矩阵

两步:

1、在shader里添加矩阵

2、引用@math.gl/core,api见下面的链接

math.gl | Overview

例子(将上面的initshader改为initshader2):

  1. initRender2() {
  2. let myExternalRenderer = {
  3. vbo: null,
  4. shaderProgram: null,
  5. a_Position: null,
  6. setup: function(context) {
  7. let gl = context.gl;
  8. // 初始化shader
  9. var VSHADER=`#version 300 es
  10. layout (location=0) in vec4 a_Position;
  11. uniform mat4 u_formMatrix;
  12. void main(){
  13. gl_Position= u_formMatrix*a_Position;
  14. }
  15. `;
  16. var FSHADER=`#version 300 es
  17. precision mediump float;
  18. out vec4 fragColor;
  19. void main(){
  20. fragColor=vec4(1.0,0.0,0.0,1.0);
  21. }
  22. `;
  23. this.shaderProgram=initWebgl2Shaders(gl, VSHADER, FSHADER)
  24. if(!this.shaderProgram){
  25. console.assert("初始化shader错误")
  26. }
  27. this.a_Position= gl.getAttribLocation(this.shaderProgram, 'a_Position')
  28. gl.enableVertexAttribArray(this.a_Position) //连接变量a_Position和缓冲区对象
  29. // 初始化bufferdata
  30. this.vbo = context.gl.createBuffer();
  31. context.gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo);
  32. let positions = new Float32Array([0, 0, 0, 1, 0, 0, 0, 1, 0]);
  33. context.gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
  34. },
  35. render: function(context) {
  36. let gl = context.gl
  37. gl.enable(gl.DEPTH_TEST); // 开启深度检测
  38. // gl.disable(gl.CULL_FACE);
  39. // gl.disable(gl.BLEND);
  40. gl.useProgram(this.shaderProgram);
  41. // 创建数据
  42. context.gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo);
  43. gl.vertexAttribPointer(this.a_Position,3,gl.FLOAT,false,0,0) //将缓冲区对象分配给a_Posiotion
  44. //旋转矩阵
  45. let u_formMatrix=gl.getUniformLocation(this.shaderProgram, 'u_formMatrix')
  46. let formMatrix=new Matrix4().translate([-1.0, -1.0, 0])
  47. gl.uniformMatrix4fv(u_formMatrix, false, formMatrix.elements)
  48. context.gl.drawArrays(gl.TRIANGLES, 0, 3);
  49. console.log(1) // 每帧检测
  50. }
  51. }
  52. externalRenderers.add(viewer, myExternalRenderer);
  53. },

最终效果:

 3、提取出颜色

提取出颜色的步骤:

1、在shader中提取出颜色

2、给颜色赋值

例子3(将例1的initshader改为initshader3):

  1. initRender3() {
  2. let myExternalRenderer = {
  3. vbo: null,
  4. shaderProgram: null,
  5. a_Position: null,
  6. a_color: null,
  7. colorBuffer: null,
  8. setup: function(context) {
  9. let gl = context.gl;
  10. // 初始化shader
  11. var VSHADER=`#version 300 es
  12. layout (location=0) in vec4 a_Position;
  13. layout (location=1) in vec4 a_color;
  14. out vec4 v_color;
  15. uniform mat4 u_formMatrix;
  16. void main(){
  17. gl_Position= u_formMatrix*a_Position;
  18. v_color=a_color;
  19. }
  20. `;
  21. var FSHADER=`#version 300 es
  22. precision mediump float;
  23. in vec4 v_color;
  24. out vec4 fragColor;
  25. void main(){
  26. fragColor=v_color;
  27. }
  28. `;
  29. this.shaderProgram=initWebgl2Shaders(gl, VSHADER, FSHADER)
  30. if(!this.shaderProgram){
  31. console.assert("初始化shader错误")
  32. }
  33. this.a_Position= gl.getAttribLocation(this.shaderProgram, 'a_Position')
  34. gl.enableVertexAttribArray(this.a_Position) //连接变量a_Position和缓冲区对象
  35. this.a_color= gl.getAttribLocation(this.shaderProgram, 'a_color')
  36. gl.enableVertexAttribArray(this.a_color) //连接变量a_color和缓冲区对象
  37. // 初始化顶点的bufferdata
  38. this.vbo = context.gl.createBuffer();
  39. context.gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo);
  40. let positions = new Float32Array([0, 0, 0, 1, 0, 0, 0, 1, 0]);
  41. context.gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
  42. // 给顶点的各个点赋予颜色
  43. this.colorBuffer=gl.createBuffer() //创建缓冲区对象
  44. gl.bindBuffer(gl.ARRAY_BUFFER,this.colorBuffer) //将缓冲区对象绑定到目标
  45. let colors=new Float32Array([1.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,1.0])
  46. gl.bufferData(gl.ARRAY_BUFFER,colors,gl.STATIC_DRAW) //向缓冲区对象写入数据
  47. },
  48. render: function(context) {
  49. let gl = context.gl
  50. gl.enable(gl.DEPTH_TEST); // 开启深度检测
  51. // gl.disable(gl.CULL_FACE);
  52. // gl.disable(gl.BLEND);
  53. gl.useProgram(this.shaderProgram);
  54. // 创建数据
  55. context.gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo);
  56. gl.vertexAttribPointer(this.a_Position,3,gl.FLOAT,false,0,0) //将缓冲区对象分配给a_Posiotion
  57. gl.bindBuffer(gl.ARRAY_BUFFER,this.colorBuffer) //将缓冲区对象绑定到目标
  58. gl.vertexAttribPointer(this.a_color,3,gl.FLOAT,false,0,0) //将缓冲区对象分配给a_color
  59. //旋转矩阵
  60. let u_formMatrix=gl.getUniformLocation(this.shaderProgram, 'u_formMatrix')
  61. let formMatrix=new Matrix4().translate([-1.0, -1.0, 0])
  62. gl.uniformMatrix4fv(u_formMatrix, false, formMatrix.elements)
  63. context.gl.drawArrays(gl.TRIANGLES, 0, 3);
  64. console.log(1) // 每帧检测
  65. }
  66. }
  67. externalRenderers.add(viewer, myExternalRenderer);
  68. },

最终效果:

4、添加动态效果

添加动态效果,通常最好的办法就是修改矩阵。

在例3的基础上,修改一下矩阵,注意动态效果需要在render里添加externalRenderers.requestRender(viewer);用来场景变化时,仍然调用该render。

例子4((将例1的initshader改为initshader4)

  1. initRender4() {
  2. let myExternalRenderer = {
  3. vbo: null,
  4. shaderProgram: null,
  5. a_Position: null,
  6. a_color: null,
  7. colorBuffer: null,
  8. i: 0,
  9. setup: function(context) {
  10. let gl = context.gl;
  11. // 初始化shader
  12. var VSHADER=`#version 300 es
  13. layout (location=0) in vec4 a_Position;
  14. layout (location=1) in vec4 a_color;
  15. out vec4 v_color;
  16. uniform mat4 u_formMatrix;
  17. void main(){
  18. gl_Position= u_formMatrix*a_Position;
  19. v_color=a_color;
  20. }
  21. `;
  22. var FSHADER=`#version 300 es
  23. precision mediump float;
  24. in vec4 v_color;
  25. out vec4 fragColor;
  26. void main(){
  27. fragColor=v_color;
  28. }
  29. `;
  30. this.shaderProgram=initWebgl2Shaders(gl, VSHADER, FSHADER)
  31. if(!this.shaderProgram){
  32. console.assert("初始化shader错误")
  33. }
  34. this.a_Position= gl.getAttribLocation(this.shaderProgram, 'a_Position')
  35. gl.enableVertexAttribArray(this.a_Position) //连接变量a_Position和缓冲区对象
  36. this.a_color= gl.getAttribLocation(this.shaderProgram, 'a_color')
  37. gl.enableVertexAttribArray(this.a_color) //连接变量a_color和缓冲区对象
  38. // 初始化顶点的bufferdata
  39. this.vbo = context.gl.createBuffer();
  40. context.gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo);
  41. let positions = new Float32Array([0, 0, 0, 1, 0, 0, 0, 1, 0]);
  42. context.gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
  43. // 给顶点的各个点赋予颜色
  44. this.colorBuffer=gl.createBuffer() //创建缓冲区对象
  45. gl.bindBuffer(gl.ARRAY_BUFFER,this.colorBuffer) //将缓冲区对象绑定到目标
  46. let colors=new Float32Array([1.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,1.0])
  47. gl.bufferData(gl.ARRAY_BUFFER,colors,gl.STATIC_DRAW) //向缓冲区对象写入数据
  48. },
  49. render: function(context) {
  50. let gl = context.gl
  51. this.i += 1
  52. gl.enable(gl.DEPTH_TEST); // 开启深度检测
  53. // gl.disable(gl.CULL_FACE);
  54. // gl.disable(gl.BLEND);
  55. gl.useProgram(this.shaderProgram);
  56. // 创建数据
  57. context.gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo);
  58. gl.vertexAttribPointer(this.a_Position,3,gl.FLOAT,false,0,0) //将缓冲区对象分配给a_Posiotion
  59. gl.bindBuffer(gl.ARRAY_BUFFER,this.colorBuffer) //将缓冲区对象绑定到目标
  60. gl.vertexAttribPointer(this.a_color,3,gl.FLOAT,false,0,0) //将缓冲区对象分配给a_color
  61. //旋转矩阵
  62. let u_formMatrix=gl.getUniformLocation(this.shaderProgram, 'u_formMatrix')
  63. let formMatrix=new Matrix4()
  64. formMatrix.rotateY(Math.PI/180 * this.i)
  65. gl.uniformMatrix4fv(u_formMatrix, false, formMatrix.elements)
  66. context.gl.drawArrays(gl.TRIANGLES, 0, 3);
  67. console.log(1) // 每帧检测
  68. externalRenderers.requestRender(viewer);
  69. }
  70. }
  71. externalRenderers.add(viewer, myExternalRenderer);
  72. },

最终效果:

5、关联相机

根据webgl的三维矩阵方程:

gl_position=ProjectionMatrix*ViewMatrix*ModelMatrix*position

可以在render里使用相机的ProjectionMatrix和ViewMatrix。(根据地球的大小,可以将三角形长宽设置在10000000m)

  1. initRender5() {
  2. let myExternalRenderer = {
  3. vbo: null,
  4. shaderProgram: null,
  5. a_Position: null,
  6. a_color: null,
  7. colorBuffer: null,
  8. i: 0,
  9. setup: function(context) {
  10. let gl = context.gl;
  11. // 初始化shader
  12. var VSHADER=`#version 300 es
  13. layout (location=0) in vec3 a_Position;
  14. layout (location=1) in vec4 a_color;
  15. out vec4 v_color;
  16. uniform mat4 u_projectionMatrix;
  17. uniform mat4 u_viewMatrix;
  18. uniform mat4 u_formMatrix;
  19. void main(){
  20. gl_Position= u_projectionMatrix*u_viewMatrix*u_formMatrix*vec4(a_Position,1.0);
  21. v_color=a_color;
  22. }
  23. `;
  24. var FSHADER=`#version 300 es
  25. precision mediump float;
  26. in vec4 v_color;
  27. out vec4 fragColor;
  28. void main(){
  29. fragColor=v_color;
  30. }
  31. `;
  32. this.shaderProgram=initWebgl2Shaders(gl, VSHADER, FSHADER)
  33. if(!this.shaderProgram){
  34. console.assert("初始化shader错误")
  35. }
  36. this.a_Position= gl.getAttribLocation(this.shaderProgram, 'a_Position')
  37. gl.enableVertexAttribArray(this.a_Position) //连接变量a_Position和缓冲区对象
  38. this.a_color= gl.getAttribLocation(this.shaderProgram, 'a_color')
  39. gl.enableVertexAttribArray(this.a_color) //连接变量a_color和缓冲区对象
  40. // 初始化顶点的bufferdata
  41. this.vbo = context.gl.createBuffer();
  42. context.gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo);
  43. let positions = new Float32Array([0, 0, 0, 10000000, 0, 0, 0, 10000000, 0]);
  44. context.gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
  45. // 给顶点的各个点赋予颜色
  46. this.colorBuffer=gl.createBuffer() //创建缓冲区对象
  47. gl.bindBuffer(gl.ARRAY_BUFFER,this.colorBuffer) //将缓冲区对象绑定到目标
  48. let colors=new Float32Array([1.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,1.0])
  49. gl.bufferData(gl.ARRAY_BUFFER,colors,gl.STATIC_DRAW) //向缓冲区对象写入数据
  50. },
  51. render: function(context) {
  52. let gl = context.gl
  53. this.i += 1
  54. gl.enable(gl.DEPTH_TEST); // 开启深度检测
  55. // gl.disable(gl.CULL_FACE);
  56. // gl.disable(gl.BLEND);
  57. gl.useProgram(this.shaderProgram);
  58. // 创建数据
  59. context.gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo);
  60. gl.vertexAttribPointer(this.a_Position,3,gl.FLOAT,false,0,0) //将缓冲区对象分配给a_Posiotion
  61. gl.bindBuffer(gl.ARRAY_BUFFER,this.colorBuffer) //将缓冲区对象绑定到目标
  62. gl.vertexAttribPointer(this.a_color,3,gl.FLOAT,false,0,0) //将缓冲区对象分配给a_color
  63. // project 矩阵
  64. let programUniformProjectionMatrix = gl.getUniformLocation(
  65. this.shaderProgram,
  66. "u_projectionMatrix"
  67. );
  68. console.log(context.camera)
  69. gl.uniformMatrix4fv(
  70. programUniformProjectionMatrix,
  71. false,
  72. context.camera.projectionMatrix
  73. );
  74. // view 矩阵
  75. let programUniformViewMatrix = gl.getUniformLocation(
  76. this.shaderProgram,
  77. "u_viewMatrix"
  78. );
  79. gl.uniformMatrix4fv(
  80. programUniformViewMatrix,
  81. false,
  82. context.camera.viewMatrix
  83. );
  84. //旋转矩阵
  85. let u_formMatrix=gl.getUniformLocation(this.shaderProgram, 'u_formMatrix')
  86. let formMatrix=new Matrix4()
  87. formMatrix.rotateY(Math.PI/180*this.i)
  88. gl.uniformMatrix4fv(u_formMatrix, false, formMatrix.elements)
  89. context.gl.drawArrays(gl.TRIANGLES, 0, 3);
  90. console.log(this.i) // 每帧检测
  91. externalRenderers.requestRender(viewer);
  92. }
  93. }
  94. externalRenderers.add(viewer, myExternalRenderer);
  95. },

最终效果:

 

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号