Cesium 实例化潜入潜出
Cesium 实例化潜入潜出
1、WebGL Instance 的原理
狭义的的WebGL 中说使用 Instance, 一般指使用 glDrawArraysInstanced
用于实例化渲染的函数。它允许在一次绘制调用中渲染多个相同的几何体实例,而无需为每个实例发起单独的绘制调用。
Three.js 就是使用这种方式, 狭义的Cesium 实例化并不是这样使用, 后面细说。
使用 glDrawArraysInstanced 的基本步骤:
- 创建并绑定缓冲区
// 创建几何体数据缓冲区(顶点位置)
const geometryBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, geometryBuffer);
const geometryData = new Float32Array([// 顶点数据 (例如:位置数据)0.0, 0.5, 0.0, // 顶点1-0.5, -0.5, 0.0, // 顶点20.5, -0.5, 0.0, // 顶点3
]);
gl.bufferData(gl.ARRAY_BUFFER, geometryData, gl.STATIC_DRAW);// 创建实例数据缓冲区(变换矩阵数据)
const instanceBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, instanceBuffer);
const instanceData = new Float32Array([// 变换数据 (每个实例的变换矩阵)1.0, 0.0, 0.0, 0.0, // 实例1的变换矩阵0.0, 1.0, 0.0, 1.0, // 实例2的变换矩阵-1.0, 0.0, 0.0, 0.0, // 实例3的变换矩阵
]);
gl.bufferData(gl.ARRAY_BUFFER, instanceData, gl.STATIC_DRAW);
- 绑定缓冲区
// 绑定几何体缓冲区
gl.bindBuffer(gl.ARRAY_BUFFER, geometryBuffer);
const positionLocation = gl.getAttribLocation(program, "a_position");
gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(positionLocation);// 绑定实例缓冲区
gl.bindBuffer(gl.ARRAY_BUFFER, instanceBuffer);
const instanceLocation = gl.getAttribLocation(program, "a_instanceTransform");
gl.vertexAttribPointer(instanceLocation, 4, gl.FLOAT, false, 4 * 4, 0);
gl.vertexAttribDivisor(instanceLocation, 1); // 每个实例使用不同的值
gl.enableVertexAttribArray(instanceLocation);
- 着色器
// 顶点着色器
attribute vec3 a_position;// 每个实例的变换数据
attribute vec4 a_instanceTransform;uniform mat4 u_projectionMatrix;
uniform mat4 u_viewMatrix;void main(void) {mat4 modelMatrix = mat4(a_instanceTransform.x, 0.0, 0.0, 0.0,0.0, a_instanceTransform.y, 0.0, 0.0,0.0, 0.0, a_instanceTransform.z, 0.0,0.0, 0.0, 0.0, 1.0);gl_Position = u_projectionMatrix * u_viewMatrix * modelMatrix * vec4(a_position, 1.0);
}// 片元着色器
void main(void) {gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // 渲染红色
}
- 绘制
// 假设我们已经设置好了所有缓冲区、着色器等
const instanceCount = 3; // 实例数量
const vertexCount = 3; // 顶点数量(单个几何体的顶点数)
gl.drawArraysInstanced(gl.TRIANGLES, 0, vertexCount, instanceCount);// 解绑相关资源
gl.bindBuffer(gl.ARRAY_BUFFER, null);
2、Cesium 实例化的原理
Cesium 的狭义实例化并不是使用 glDrawArraysInstanced 实现的, 比如下面的代码, 像这种"普通的几何体"。
但并不是没有使用 glDrawArraysInstanced 实现实例化, 比如广告牌, “特殊的几何体”。
// 创建5个立方体
let dimensions = new Cesium.Cartesian3(1.0, 1.0, 1.0);
let boxGeometry = Cesium.BoxGeometry.fromDimensions({vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,dimensions: dimensions,
});const instances = [];for (let i = 0; i < 5; ++i) {const offsetX = Math.random() * 0.05;const offsetY = Math.random() * 0.05;const boxModelMatrix = Cesium.Matrix4.multiplyByUniformScale(Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(info.lon + offsetX, info.lat + offsetY),),500.0,new Cesium.Matrix4(),);instances.push(new Cesium.GeometryInstance({geometry: boxGeometry,modelMatrix: boxModelMatrix,attributes: {color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.fromRandom({ alpha: 1.0 }),),},}),);
}window.primitive = viewer.scene.primitives.add(new Cesium.Primitive({geometryInstances: instances,appearance: new Cesium.PerInstanceColorAppearance({translucent: false,closed: true,}),}),
);
创建流程概览:
Primitive.prototype.update() {loadAsynchronous()
}function loadAsynchronous() {// 根据参数创建对应的几何体, 对于上面的例子, 这里会重复执行5次, 即使参数相同promises.push(createGeometryTaskProcessors[i].scheduleTask);// 合并几何体combineGeometryTaskProcessor.scheduleTask();|| -- PrimitivePipeline.combineGeometry()|| -- geometryPipeline() {// 关键: 将所有顶点应用实例的模型矩阵transformToWorldCoordinates();}}
还有很多其他关键操作, 比如顶点索引的合并, 实例对应的自定义属性, 包围盒等。这里只关心顶点位置数据。
3、总结
Three.js 方式:
Cesium 方式:
cesium在提交给GPU之前已经将顶点应用了实例对应的模型矩阵。
相关文章:

Cesium 实例化潜入潜出
Cesium 实例化潜入潜出 1、WebGL Instance 的原理 狭义的的WebGL 中说使用 Instance, 一般指使用 glDrawArraysInstanced 用于实例化渲染的函数。它允许在一次绘制调用中渲染多个相同的几何体实例,而无需为每个实例发起单独的绘制调用。 Three.js 就是使用这种方…...

java引入jedis并且关于开放redis端口问题
博主主页: 码农派大星. 数据结构专栏:Java数据结构 数据库专栏:数据库 JavaEE专栏:JavaEE 软件测试专栏:软件测试 关注博主带你了解更多知识 目录 1. 引入jedis 编辑 2. 关于java客户端开放redis端口问题 3. 连接redis服务器 redis服务器在官网公开了使用的协议: resp…...
【人工智能】用Python实现情感分析:从简单词典到深度学习方法的演进
《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 情感分析是自然语言处理(NLP)中的一个重要任务,其目的是通过分析文本内容,识别出其中的情感极性,如正面、负面或中性。随着技术的不断…...
关系型数据库的完整性和一致性
完整性 1.实体完整性 - 每一个实体都是独一无二的,没有冗余 --主键/唯一索引 2.参照完整性 - 外键 3.域完整性 - 存储的数据都是有效的数据 --数据类型/数据长度/非空约束/检查约束/ 检查约束: alter table tb_score add constraint ck_score_scmar…...
设计模式の命令访问者迭代器模式
文章目录 前言一、命令模式二、访问者模式三、迭代器模式 前言 本篇是关于设计模式中命令模式、访问者模式、以及迭代器模式的学习笔记。 一、命令模式 命令模式是一种行为型设计模式,其核心目的在于将命令的发送者和接受者解耦,提供一个中间层对命令进行…...
信息系统项目管理 -冲突管理
信息系统项目管理题 冲突管理: 项目管理信息系统包括()软件,用于监督资源的使用情况,协助确保合适的资源适时、适地的用于合适活动。 A资源管理或进度计划 BCRM系统 C采购系统或智能分析 DBOM系统 答案:A …...

Gmsh有限元网格剖分(Python)---点、直线、平面的移动
Gmsh有限元网格剖分(Python)—点、直线、平面的移动和旋转 最近在学习有限元的网格剖分算法,主要还是要参考老外的开源Gmsh库进行,写一些博客记录下学习过程,方便以后回忆嘞。 Gmsh的官方英文文档可以参考:gmsh.pdf 但咋就说&a…...

山景BP1048增加AT指令,实现单片机串口控制播放音乐(一)
1、设计目的 山景提供的SDK是蓝牙音箱demo,用户使用ADC按键或者IR遥控器,进行人机交互。然而现实很多场景,需要和单片机通信,不管是ADC按键或者IR接口都不适合和单片机通信。这里设计个AT指令用来和BP1048通信。AT指令如下图所示…...
SMMU软件指南SMMU编程之全局错误和最小配置
安全之安全(security)博客目录导读 目录 一、全局错误 二、最小配置 一、全局错误 与编程接口相关的全局错误会报告到适当的 SMMU_(*_)GERROR 寄存器,而不是通过基于内存的事件队列。这些错误通常是严重的,例如导致 SMMU 停止向前推进。例如…...

CPU条件下Pytorch、jupyter环境配置
一、创建虚拟环境 查看虚拟环境 conda env list 创建python虚拟环境 conda create -n minist python3.11 激活虚拟环境 conda activate minist 查看虚拟环境下有哪些包 pip list 二、安装pytorch 切换清华源 conda config --add channels https://mirrors.tuna.tsing…...

【自用】通信内网部署rzgxxt项目_01,后端pipeDemo部署(使用nssm.exe仿照nohup)
做完这些工作之后,不要忘记打开 Windows Server 的防火墙端口,8181、8081、8080、22、443、1521 做完这些工作之后,不要忘记打开 Windows Server 的防火墙端口,8181、8081、8080、22、443、1521 做完这些工作之后,不要…...
Ubuntu 安装实时内核指南
在运行需要高精度和低延迟响应的机器人驱动程序时,安装一个具备实时内核(Real-Time Kernel)的 Ubuntu 系统是至关重要的。若缺乏实时系统的支持,高频率的控制指令可能会导致机器人运动轨迹不流畅,甚至产生抖动现象。以…...
MySQL 主从复制与高可用
在现代分布式系统中,数据库的高可用性和可靠性至关重要。MySQL 提供了主从复制(Master-Slave Replication)机制来实现数据的冗余和容错,保证在主数据库发生故障时能够继续提供服务。而在此基础上,通过进一步的高可用架…...

RCE总结
文章目录 常见漏洞执行函数:1.系统命令执行函数2.代码执行函数 命令拼接符读取文件命令绕过:空格过滤绕过关键字绕过长度过滤绕过无参数命令执行绕过无字母数字绕过利用%0A截断利用回溯绕过利用create_function()代码注入无回显RCE1.反弹shell2.dnslog外…...

基于UNITY3D的照片墙演示项目技术分享
unity实现超大图片墙演示,由于拥有海量图片,使用了CPU 多线程,unity dots技术,图片组成文字部分,使用了点阵图技术,提取文字像素。 (关于点阵介绍) 点阵字体是把每一个字符都分成1616或2424个点…...

随手记:小程序兼容后台的wangEditor富文本配置链接
场景: 在后台配置wangEditor富文本,可以文字配置链接,图片配置链接,产生的json格式为: 例子: <h1><a href"https://uniapp.dcloud.net.cn/" target"_blank"><span sty…...

maven项目运行时NoSuchMethodError问题排查记录(依赖冲突解决)
控制台异常如下: Handler dispatch failed; nested exception is java.lang.NoSuchMethodError: org.apache.commons.io.input.BoundedInputStream.builder()Lorg/apache/commons/io/input/BoundedInputStream$Builder;问题明显,根据NoSuchMethodError…...

ECharts关系图-关系图11,附视频讲解与代码下载
引言: 关系图(或称网络图、关系网络图)在数据可视化中扮演着至关重要的角色。它们通过节点(代表实体,如人、物体、概念等)和边(代表实体之间的关系或连接)的形式,直观地…...
【C语言】动态内存管理:详解malloc和free函数
前言 在C语言编程中,动态内存分配是一个非常重要的概念。与静态内存分配不同,动态内存分配允许程序在运行时根据需要分配和释放内存,从而更加灵活地管理内存资源。特别是在一些数据结构的引用中经常需要使用,下面我们就详细讲解一…...

EGO Swarm翻译
目录 摘要 Ⅰ 介绍 Ⅱ 相关工作 A . 单四旋翼局部规划 B . 拓扑规划 C. 分布式无人机集群 Ⅲ 基于梯度的局部规划隐式拓扑轨迹生成 A.无需ESDF梯度的局部路径规划 B.隐式拓扑轨迹生成 Ⅳ 无人机集群导航 A 机间避碰 B. 定位漂移补偿 C. 从深度图像中去除agent Ⅴ …...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...

Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...

Golang——9、反射和文件操作
反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一:使用Read()读取文件2.3、方式二:bufio读取文件2.4、方式三:os.ReadFile读取2.5、写…...