WebGL系列教程六(纹理映射与立方体贴图)

news2024/11/14 12:20:09

目录

  • 1 前言
  • 2 思考题
  • 3 纹理映射介绍
  • 4 怎么映射?
  • 5 开始绘制
    • 5.1 声明顶点着色器和片元着色器
    • 5.2 修改顶点的颜色为纹理坐标
    • 5.3 指定顶点位置和纹理坐标的值
    • 5.4 获取图片成功后进行绘制
    • 5.5 效果
    • 5.6 完整代码
  • 6 总结

1 前言

  上一讲我们讲了如何使用索引绘制彩色立方体,还留了一个思考题:怎么让立方体的每个面都保持一个颜色?这一讲我们就来解决这个问题,并引出纹理映射和立方体贴图。

2 思考题

  怎么让立方体的每个面都保持一个颜色?那当然是让每个面的两个三角形都保持一个颜色就行了,那怎么让每个三角形都保持一个颜色呢?因为三角形的颜色是通过顶点的颜色插值出来的,自然是让三角形的每个顶点都保持一个颜色就可以了。
  但是这样又产生了新问题,因为顶点是公用的,难道给每个顶点多个颜色吗?答:是的。
在这里插入图片描述
  比如v0这个顶点,它被三个面公用,分别是前面、上面、右面。那么也就意味着它会有三个颜色,因为我们要让立方体每个表面都是一个颜色。回顾一下上一讲我们是怎么给顶点颜色的:

//顶点和颜色
let verticesColors = new Float32Array([
     1.0, 1.0, 1.0,   1.0,1.0,1.0,//v0 近平面 右上 颜色
    -1.0, 1.0, 1.0,   1.0,0.0,1.0,//v1 近平面 左上 颜色
    -1.0,-1.0, 1.0,   1.0,0.0,1.0,//v2 近平面 左下 颜色
     1.0,-1.0, 1.0,   1.0,1.0,0.0,//v3 近平面 右下 颜色
     1.0,-1.0,-1.0,   1.0,0.0,1.0,//v4 远平面 右下 颜色
    -1.0,-1.0,-1.0,   1.0,1.0,1.0,//v5 远平面 左下 颜色
    -1.0, 1.0,-1.0,   0.0,0.0,1.0,//v6 远平面 左上 颜色
     1.0, 1.0,-1.0,   0.0,1.0,1.0 //v7 远平面 右上 颜色
]);
//顶点索引
let indices = new Uint8Array([
    0,1,2,  0,2,3,//近平面
    4,5,6,  4,6,7,//远平面
    1,2,5,  1,5,6,//左平面
    0,3,4,  0,4,7,//右平面
    3,4,2,  3,5,2,//下平面
    0,7,6,  0,1,6 //上平面
]);

  现在一个顶点三个颜色,那岂不是说顶点不够用了?是的,所以每个顶点我们要写三次。也就是说,这次顶点不能公用了。我们对上述代码进行修改

const verticesColors = new Float32Array([
  // 前面
  -1.0, -1.0,  1.0,     1.0, 0.0,1.0,//v2 红色
   1.0, -1.0,  1.0,     1.0, 0.0,1.0,//v3 红色
   1.0,  1.0,  1.0,     1.0, 0.0,1.0,//v0 红色
  -1.0,  1.0,  1.0,     1.0, 0.0,1.0,//v1 红色

  // 后面
  -1.0, -1.0, -1.0,     0.0, 1.0, 0.0,//v5 绿色
   1.0, -1.0, -1.0,     0.0, 1.0, 0.0,//v4 绿色
   1.0,  1.0, -1.0,     0.0, 1.0, 0.0,//v7 绿色
  -1.0,  1.0, -1.0,     0.0, 1.0, 0.0,//v6 绿色

  // 上面
  -1.0,  1.0,  1.0,     0.0, 0.0,1.0,//v1 蓝色
   1.0,  1.0,  1.0,     0.0, 0.0,1.0,//v0 蓝色
   1.0,  1.0, -1.0,     0.0, 0.0,1.0,//v7 蓝色
  -1.0,  1.0, -1.0,     0.0, 0.0,1.0,//v6 蓝色

  // 下面
  -1.0, -1.0,  1.0,     0.0, 0.0,0.0,//v2 黑色
   1.0, -1.0,  1.0,     0.0, 0.0,0.0,//v3 黑色
   1.0, -1.0, -1.0,     0.0, 0.0,0.0,//v4 黑色
  -1.0, -1.0, -1.0,     0.0, 0.0,0.0,//v5 黑色

  // 左面
  -1.0, -1.0, -1.0,     0.0, 1.0,1.0,//v5 青色
  -1.0, -1.0,  1.0,     0.0, 1.0,1.0,//v2 青色
  -1.0,  1.0,  1.0,     0.0, 1.0,1.0,//v1 青色
  -1.0,  1.0, -1.0,     0.0, 1.0,1.0,//v6 青色

  // 右面
   1.0, -1.0,  1.0,     1.0, 1.0,1.0,//v3 白色
   1.0, -1.0, -1.0,     1.0, 1.0,1.0,//v4 白色
   1.0,  1.0, -1.0,     1.0, 1.0,1.0,//v7 白色
   1.0,  1.0,  1.0,     1.0, 1.0,1.0,//v0 白色
]);
//顶点索引
let indices = new Uint8Array([
   0, 1, 2, 0, 2, 3, // 前面
   4, 5, 6, 4, 6, 7, // 后面
   8, 9, 10, 8, 10, 11, // 上面
   12, 13, 14, 12, 14, 15, // 下面
   16, 17, 18, 16, 18, 19, // 左面
   20, 21, 22, 20, 22, 23  // 右面
]);

  看下效果,prefect!
在这里插入图片描述

3 纹理映射介绍

  其实这个词语还是比较好理解。见名知意,大概意思就是把纹理映射到某个地方,纹理是什么?现在你可以简单的认为纹理就是一张图片。把一张二维的图片映射到一个三维物体的表面,就叫纹理映射。
在这里插入图片描述

4 怎么映射?

  很简单,你只需要将立方体的的和图片的位置对应起来告诉WebGL就可以了。比如立方体的左上角对应图片的左上角,立方体右上角对应图片右上角,左下角、右下角类似。那么中间的怎么办?中间的WebGL会自动帮我们去映射。纹理坐标我们用uv来表示,相当于xy。不论图片是什么尺寸的,图片的左下角uv始终是【0,0】,右上角始终是【1,1】,这一点也是WebGL帮我们实现的。
在这里插入图片描述

5 开始绘制

5.1 声明顶点着色器和片元着色器

<script id="vertex-shader" type="x-shader/x-vertex">
    //顶点位置
    attribute vec4 a_Position;
    //纹理坐标
    attribute vec2 a_TexCoord;
    //传递纹理坐标
    varying vec2 v_TexCoord;
    void main(){
        gl_Position = a_Position;
        //直接将纹理坐标赋值给传递变量
        v_TexCoord = a_TexCoord;
    }
</script>
<script id="fragment-shader" type="x-shader/x-fragment">
    precision highp float;
    //采样器,固定写法
    uniform sampler2D u_Sampler;
    //接收顶点着色器传过来的值
    varying vec2 v_TexCoord;
    void main(){
    	//到某个纹理坐标去采样,也是固定写法
        gl_FragColor = texture2D(u_Sampler,v_TexCoord);
    }
</script>

5.2 修改顶点的颜色为纹理坐标

  前面我们给立方体的表面赋值的是颜色,现在我们把它变为纹理坐标

const verticesColors = new Float32Array([
  // 前面
   -1.0, -1.0,  1.0,   0.0, 0.0,//v2 图片左下角纹理坐标
    1.0, -1.0,  1.0,   1.0, 0.0,//v3 图片左下角纹理坐标
    1.0,  1.0,  1.0,   1.0, 1.0,//v0 图片右下角纹理坐标
   -1.0,  1.0,  1.0,   0.0, 1.0,//v1 图片左上角纹理坐标

   // 后面
   -1.0, -1.0, -1.0,   0.0, 0.0,//v5 同上
    1.0, -1.0, -1.0,   1.0, 0.0,//v4 同上
    1.0,  1.0, -1.0,   1.0, 1.0,//v7 同上
   -1.0,  1.0, -1.0,   0.0, 1.0,//v6 同上

   // 上面
   -1.0,  1.0,  1.0,   0.0, 0.0,//v1 同上
    1.0,  1.0,  1.0,   1.0, 0.0,//v0 同上
    1.0,  1.0, -1.0,   1.0, 1.0,//v7 同上
   -1.0,  1.0, -1.0,   0.0, 1.0,//v6 同上

   // 下面
    -1.0, -1.0, 1.0,   0.0, 0.0,//v2 同上
    1.0,  -1.0, 1.0,   1.0, 0.0,//v3 同上
    1.0,  -1.0,-1.0,   1.0, 1.0,//v4 同上
    -1.0, -1.0,-1.0,   0.0, 1.0,//v5 同上

   // 左面
   -1.0, -1.0, -1.0,   0.0, 0.0,//v5 同上
   -1.0, -1.0,  1.0,   1.0, 0.0,//v2 同上
   -1.0,  1.0,  1.0,   1.0, 1.0,//v1 同上
   -1.0,  1.0, -1.0,   0.0, 1.0,//v6 同上

   // 右面
    1.0, -1.0,  1.0,   0.0, 0.0,//v3 同上
    1.0, -1.0, -1.0,   1.0, 0.0,//v4 同上
    1.0,  1.0, -1.0,   1.0, 1.0,//v7 同上
    1.0,  1.0,  1.0,   0.0, 1.0,//v0 同上
]);


const indices = new Uint8Array([
   0, 1, 2, 0, 2, 3, // 前面
   4, 5, 6, 4, 6, 7, // 后面
   8, 9, 10, 8, 10, 11, // 上面
   12, 13, 14, 12, 14, 15, // 下面
   16, 17, 18, 16, 18, 19, // 左面
   20, 21, 22, 20, 22, 23  // 右面
]);

5.3 指定顶点位置和纹理坐标的值

 //顶点
 let vertexColorBuffer = gl.createBuffer();
 gl.bindBuffer(gl.ARRAY_BUFFER,vertexColorBuffer);
 gl.bufferData(gl.ARRAY_BUFFER,verticesColors,gl.STATIC_DRAW);
 let FSIZE = verticesColors.BYTES_PER_ELEMENT;
 let a_Position = gl.getAttribLocation(program,'a_Position');
 gl.vertexAttribPointer(a_Position,3,gl.FLOAT,false,FSIZE*5,0);
 gl.enableVertexAttribArray(a_Position);
 //指定纹理坐标值
 let a_TexCoord = gl.getAttribLocation(program,'a_TexCoord');
 gl.vertexAttribPointer(a_TexCoord,2,gl.FLOAT,false,5*FSIZE,3*FSIZE);
 gl.enableVertexAttribArray(a_TexCoord);

5.4 获取图片成功后进行绘制

let image = new Image();
image.src = 'static/sky.jpg';
image.onload = function(){
    console.log('image ok');
	//创建纹理对象
    let texture = gl.createTexture();
    //获取采样器
    let u_Sampler = gl.getUniformLocation(program,'u_Sampler');
    //反转Y轴,canvas的Y轴和WebGL的Y轴方向是反的
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1);
    //启用0号纹理
    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D,texture);
    //设置纹理为,缩小纹理时,取纹理坐标周围四个像素的颜色均值
    gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);
    //设置对象使用的图片,mipmap层级,图像的格式,纹理的格式,纹理数据类型,图片
    gl.texImage2D(gl.TEXTURE_2D,0,gl.RGB,gl.RGB,gl.UNSIGNED_BYTE,image);
    //将0号纹理赋值给采样器
    gl.uniform1i(u_Sampler,0);


    //绑定索引缓冲
    let indexBuffer =  gl.createBuffer();
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indexBuffer);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,indices,gl.STATIC_DRAW);
    //清空颜色缓冲和深度缓冲
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    //绘制
    //顶点索引数组如果是Uint8Array,就是UNSIGNED_BYTE,表示数组里的值在0-2^8-1(255)
    //................Uint16Array,就是UNSIGNED_SHORT,表示数组里的值在0-2^16-1(65535)
    //................Uint32Array,就是UNSIGNED_INT,表示数组里的值在0-2^32-1(4294967295)
    gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_BYTE, 0);
};

5.5 效果

  为了能看到明显的效果,我将立方体进行了旋转,具体如何旋转,我们后面的文章会进行介绍。
在这里插入图片描述

5.6 完整代码

// Create a cube
//    v6----- v7
//   /|      /|
//  v1------v0|
//  | |     | |
//  | |v5---|-|v4
//  |/      |/
//  v2------v3
const verticesColors = new Float32Array([
    // 前面
    -1.0, -1.0,  1.0,   0.0, 0.0,//v2 图片左下角纹理坐标
     1.0, -1.0,  1.0,   1.0, 0.0,//v3 图片左下角纹理坐标
     1.0,  1.0,  1.0,   1.0, 1.0,//v0 图片右下角纹理坐标
    -1.0,  1.0,  1.0,   0.0, 1.0,//v1 图片左上角纹理坐标

    // 后面
    -1.0, -1.0, -1.0,   0.0, 0.0,//v5 同上
     1.0, -1.0, -1.0,   1.0, 0.0,//v4 同上
     1.0,  1.0, -1.0,   1.0, 1.0,//v7 同上
    -1.0,  1.0, -1.0,   0.0, 1.0,//v6 同上

    // 上面
    -1.0,  1.0,  1.0,   0.0, 0.0,//v1 同上
     1.0,  1.0,  1.0,   1.0, 0.0,//v0 同上
     1.0,  1.0, -1.0,   1.0, 1.0,//v7 同上
    -1.0,  1.0, -1.0,   0.0, 1.0,//v6 同上

    // 下面
     -1.0, -1.0, 1.0,   0.0, 0.0,//v2 同上
     1.0,  -1.0, 1.0,   1.0, 0.0,//v3 同上
     1.0,  -1.0,-1.0,   1.0, 1.0,//v4 同上
     -1.0, -1.0,-1.0,   0.0, 1.0,//v5 同上

    // 左面
    -1.0, -1.0, -1.0,   0.0, 0.0,//v5 同上
    -1.0, -1.0,  1.0,   1.0, 0.0,//v2 同上
    -1.0,  1.0,  1.0,   1.0, 1.0,//v1 同上
    -1.0,  1.0, -1.0,   0.0, 1.0,//v6 同上

    // 右面
     1.0, -1.0,  1.0,   0.0, 0.0,//v3 同上
     1.0, -1.0, -1.0,   1.0, 0.0,//v4 同上
     1.0,  1.0, -1.0,   1.0, 1.0,//v7 同上
     1.0,  1.0,  1.0,   0.0, 1.0,//v0 同上
]);


const indices = new Uint8Array([
    0, 1, 2, 0, 2, 3, // 前面
    4, 5, 6, 4, 6, 7, // 后面
    8, 9, 10, 8, 10, 11, // 上面
    12, 13, 14, 12, 14, 15, // 下面
    16, 17, 18, 16, 18, 19, // 左面
    20, 21, 22, 20, 22, 23  // 右面
]);
gl.viewport(0, 0, canvas.width, canvas.height);
gl.enable(gl.DEPTH_TEST);
//顶点
let vertexColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,vertexColorBuffer);
gl.bufferData(gl.ARRAY_BUFFER,verticesColors,gl.STATIC_DRAW);
let FSIZE = verticesColors.BYTES_PER_ELEMENT;
let a_Position = gl.getAttribLocation(program,'a_Position');
gl.vertexAttribPointer(a_Position,3,gl.FLOAT,false,FSIZE*5,0);
gl.enableVertexAttribArray(a_Position);
//指定纹理坐标值
let a_TexCoord = gl.getAttribLocation(program,'a_TexCoord');
gl.vertexAttribPointer(a_TexCoord,2,gl.FLOAT,false,5*FSIZE,3*FSIZE);
gl.enableVertexAttribArray(a_TexCoord);
let image = new Image();
image.src = 'static/sky.jpg';
image.onload = function(){
    console.log('image ok');
	//创建纹理对象
    let texture = gl.createTexture();
    //获取采样器
    let u_Sampler = gl.getUniformLocation(program,'u_Sampler');
    //反转Y轴,canvas的Y轴和WebGL的Y轴方向是反的
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1);
    //启用0号纹理
    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D,texture);
    //设置纹理为,缩小纹理时,取纹理坐标周围四个像素的颜色均值
    gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);
    //设置对象使用的图片,mipmap层级,图像的格式,纹理的格式,纹理数据类型,图片
    gl.texImage2D(gl.TEXTURE_2D,0,gl.RGB,gl.RGB,gl.UNSIGNED_BYTE,image);
    //将0号纹理赋值给采样器
    gl.uniform1i(u_Sampler,0);


    //绑定索引缓冲
    let indexBuffer =  gl.createBuffer();
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indexBuffer);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,indices,gl.STATIC_DRAW);
    //清空颜色缓冲和深度缓冲
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    //绘制
    //顶点索引数组如果是Uint8Array,就是UNSIGNED_BYTE,表示数组里的值在0-2^8-1(255)
    //................Uint16Array,就是UNSIGNED_SHORT,表示数组里的值在0-2^16-1(65535)
    //................Uint32Array,就是UNSIGNED_INT,表示数组里的值在0-2^32-1(4294967295)
    gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_BYTE, 0);
};

6 总结

  本节我们从如何将立方体每个面的颜色改为相同的颜色开始,介绍到了如何将图片贴到立方体的表面,系统的分析了为什么不能再共用顶点,并将代码进行了修改,以及讲解了纹理坐标的使用。这一节的内容相对较多,但理解起来并不难,希望读者认真体会,回见~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2128339.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

牛客小白月赛99(上)

材料打印 题目描述 登录—专业IT笔试面试备考平台_牛客网 运行代码 #include<iostream> using namespace std; int main(){int T;cin>>T;while(T--){ long long int a,b,x,y;cin>>a>>b>>x>>y;if(x<y){cout<<a*xb*y<<end…

微软数据库的SQL注入漏洞解析——Microsoft Access、SQLServer与SQL注入防御

说明:本文仅是用于学习分析自己搭建的SQL漏洞内容和原理,请勿用在非法途径上,违者后果自负,与笔者无关;本文开始前请认真详细学习《‌中华人民共和国网络安全法》‌及其相关法规内容【学法时习之丨网络安全在身边一图了解网络安全法_中央网络安全和信息化委员会办公室】 。…

Luigi:一个强大的Python模块,构建复杂的批处理作业管道的高效工具

在现代数据处理的大潮中&#xff0c;构建和管理复杂的数据管道是极其重要的一环。Luigi&#xff0c;作为一个强大的Python模块&#xff0c;为用户提供了构建复杂的批处理作业管道的高效工具。它不仅能够处理依赖关系、工作流管理、可视化等功能&#xff0c;还内置对Hadoop的支持…

架构与业务的一致性应用:实现企业战略目标和合规管理的全面指南

在当今快速变化的数字经济中&#xff0c;信息架构已成为企业实现其业务目标、优化运营效率和确保数据安全的关键工具。 一个成功的信息架构不仅要与企业的战略目标紧密对齐&#xff0c;还必须遵循日益严格的合规性要求&#xff0c;以保护敏感数据并满足法规规定。《信息架构&a…

Django 创建好的模块怎么在后台显示

1、配置模型及其需要显示的数据 刚才创建好的tests的增删改查&#xff0c;在后台是不显示的&#xff0c;所以需要进行配置,在刚才创建好的模块里找到admin.py文件&#xff0c;在里面进行如下配置 from django.contrib import adminfrom . import models from .models import …

【多线程】深入剖析定时器的应用

&#x1f490;个人主页&#xff1a;初晴~ &#x1f4da;相关专栏&#xff1a;多线程 / javaEE初阶 在软件开发中&#xff0c;有一些代码逻辑并不需要立马就被执行&#xff0c;可能需要等一段时间在执行。就好像我们会用闹钟来提醒我们过一段时间后要做某事一样&#xff0c;代码…

电脑文件怎么加密?文件加密方法介绍

随着数字化时代的到来&#xff0c;电脑文件的安全性问题日益凸显。为了保护个人隐私和企业数据&#xff0c;文件加密成为了一项重要的安全措施。本文将详细介绍几种常见的电脑文件加密方法&#xff0c;帮助你更好地保护自己的数据安全。 超级加密3000 超级加密3000提供了两种主…

哪款骨传导耳机适合运动?健身党无广安利五款有用的骨传导耳机!

作为一名耳机爱好者&#xff0c;我的耳机收藏可以说是丰富多样&#xff0c;从追求极致音质的头戴式&#xff0c;到便于携带的入耳式&#xff0c;再到近年来兴起的骨传导耳机&#xff0c;我都有所体验。在众多选择中&#xff0c;我最终偏爱上了骨传导耳机&#xff0c;它以其独特…

【Cadence26】无原理图直接绘制PCB项目的问题总结

【转载】Cadence Design Entry HDL 使用教程 【Cadence01】Cadence PCB Edit相对延迟与绝对延迟的显示问题 【Cadence02】Allegro引脚焊盘Pin设置为透明 【Cadence03】cadence不小心删掉钢网层怎么办&#xff1f; 【Cadence04】一般情况下Allegro PCB设计时的约束规则设置&a…

I-RNTI是什么?

I-RNTI是Inactive RNTI的缩写&#xff0c;它是per RNA配置的一个参数, 主要作用就是UE在RRCResume的时候, 方便new gNB去获取UE之前的锚点gNB(从而获取UE上下文)。 在R2-1812504中有关I-RNTI的agreement如上图&#xff1a; 1 gNB 在suspend消息中为 UE 配置full I-RNTI 和shor…

AI网盘搜索 1.2.6 智能文件搜索助手,一键搜索所有资源

对于经常需要处理大量文件的人来说&#xff0c;AI网盘检索简直是救星。它提供了智能对话式搜索功能&#xff0c;只需用自然语言描述就能找到需要的文件。此外&#xff0c;它还广泛支持各种文件类型&#xff0c;从文档到图片&#xff0c;全面覆盖。精准定位功能让您能够快速找到…

在对接电影票API时如何快速进行错误处理和调试

在对接电影票API时&#xff0c;进行有效的错误处理和调试是确保用户体验和系统稳定性的关键。以下是一些步骤和建议&#xff1a; 1.阅读API文档&#xff1a; 在开始对接前&#xff0c;彻底理解API文档中关于错误处理的部分&#xff0c;了解可能返回的所有错误码和它们的含义。…

微信小程序 === 长列表性能优化

目录 怎么做到的&#xff1f; 环境准备 使用开发者工具调试 开始迁移 在真机上预览效果 配置 We 分析 AB 实验 快捷切换入口 如何识别当前页面是否使用 Skyline 滚动容器及其应用场景 长列表 ScrollView 的三种模式 列表模式 自定义模式 嵌套模式 可拖拽容器 对…

启明云端乐鑫代理商,乐鑫ESP32无线芯片方案,物联网设备WiFi联动控制

随着智能和远程技术的飞速发展&#xff0c;物联网(IoT)逐渐出现在我们生活的每一个角落。乐鑫以其创新的无线通信技术&#xff0c;正成为智能家居、工业自动化和医疗设备等领域的推动者。 无线WiFi芯片模组不仅提供了强大的数据处理能力&#xff0c;还赋予了设备以直观的交互方…

香橙派模型转换以及部署二

由于想更新RKNN-Tookl2的版本&#xff0c;重新做一下记录。 上一篇文章安装的是RKNN-Tookl2 v1.5.2&#xff1a; 香橙派转换模型以及在开发板上部署-CSDN博客 现在记录一下RKNN-Tookl2 v2.0.0beta0版本&#xff0c;使用起来更方便&#xff0c;且可使用的功能更多一些&#x…

容联云容犀Copilot&Agent入选《中国 AI Agent 产品罗盘》

近日&#xff0c;InfoQ研究中心推出《中国AI Agent应用研究报告》&#xff0c;并在报告中对现行的中国AI Agent产品进行梳理总结&#xff0c;并形成《中国AI Agent产品罗盘》。 作为“营销服”领域垂直类Agent&#xff0c;容联云容犀Copilot&#xff06;Agent入选2024中国AI A…

天地一体化物联网:挑战与机遇

这篇论文的标题是《Space-Terrestrial Integrated Internet of Things: Challenges and Opportunities》&#xff0c;作者包括Juan A. Fraire, Oana Iova, 和 Fabrice Valois。文章发表在2022年12月的IEEE Communications Magazine上。论文主要探讨了如何将卫星通信与物联网&am…

vue3中的实例

实例类型 Vue2&#xff1a;每个Vue应用都是new Vue创建的一个新实例&#xff0c;创建的时候将data作为property添加到响应式系统中 vue3&#xff1a;createApp创建一个Application Instance、应用实例用来注册全局内容&#xff0c;大多数方法支持链式调用&#xff0c;返回实例…

C++当中的多态(二)

(三&#xff09;final和override关键字 在继承和多态当中我们还会很经常看到这两个关键字final和override。这两个关键字的作用其实很简单。 final关键字字面意思上理解就是我们这个虚函数是最后一个虚函数&#xff0c;之后不能够被重写。所以我们以后想要定义一个虚函数只能够…

word文档的读入(7)

获取了标准答案和学生答案后&#xff0c;就可以计算每位同学的填空题分数啦。我们将分数累加到studentData字典里的scoreTwo键中。需要注意的是&#xff0c;使用这个键之前&#xff0c;必须先在第一个for循环里和第二个for循环外&#xff0c;对它进行初始化赋值为0&#xff0c;…