WebGL,真正进入三维的世界

UCD9081EVM电源时序管理:硬件配置与GUI操作全解析 电源时序管理是复杂电子系统设计的核心环节,它通过精确控制多路电源的上电/下电顺序,确保核心芯片免受浪涌电流或电压倒灌的损害。其原理基于状态机逻辑与电压监控,技术价值在于将硬连线时序转化为可编程配置,极大提升了系统可靠性与设计灵活性。在服务器、通信设备、工控系统等高可靠性应用场景中,时序控制器是实现稳定启动与故障保护的关键。本文以德州仪器UCD9081评估模块为例,深入剖析其硬件跳线配置与图形用户界面操作,涵盖I2C地址设置、电压监控分压计算、时序条件与故障响应策略等工程实践要点,帮助工程师快速掌握这一电源时 阅读详情

一、在此之前

在之前的文章中,我想大家已经对WebGL有了一个大体的了解,不过为了凑字数,我在这篇文章的开头再稍微回顾一下,如果我们需要使用WebGL来绘制图像需要走完以下这五步:

1、从canvas元素中获取webgl context

2、利用GLSL ES语言,编写顶点着色器和片元着色器,并成对应的着色器程序

3、准备好你想要绘制的图像的顶点数据,并写入缓冲区

4、把着色器中的变量与载有顶点数据的缓冲区对应起来

5、最后执行着色器程序,并在canvas上绘制出图形

当然,并不是说所有的WebGL程序都必须按这样的逻辑进行,这里只是让大家对WebGL有一个基本的概念,而那些项目中使用到的真正的WebGL程序要比这复杂得多。

为了使得我们能集中精力去编写那些酷炫的WebGL程序,我把上面这些基本的步骤封装在几个工具类中,大家只要在页面里引入附件中的gl-core-min.js即可。在gl-core文件中,第一个提供给大家使用的是Program类,用于创建和管理着色器程序,具体使用如下:

<div class="km_insert_code" style="text-align: left;">

    var program = new Program(gl);

    // 载入顶点着色器
    program.attach(VERTEX_SHADER_SOURCE, gl.VERTEX_SHADER);
    // 载入片元着色器
    program.attach(FRAGMENT_SHADER_SOURCE, gl.FRAGMENT_SHADER);
    program.link();
    program.bind();

</div>

第二个提供给大家使用的是Buffer类,用于创建和管理数据缓冲区,具体使用如下:

<div class="km_insert_code" style="text-align: left;">

    // 创建顶点数据缓冲区
    var vertexBuffer = new Buffer(gl, gl.ARRAY_BUFFER);

    // 向缓存区写入数据
    vertexBuffer.write(modelObject.vertex, gl.STATIC_DRAW);
    // 是缓冲区中的数据和着色器中的a_VertexPosition变量对应起来
    vertexBuffer.bind(programAttribs.a_VertexPosition, 3, gl.FLOAT);

</div>

除此以外,由于三维图形绘制还会涉及到大量的矩阵或向量运算,我们需要一些数学工具辅助我们的开发,这里给大家介绍一个库——gl-matrix(http://glmatrix.net/)。同样,大家只要在页面里引入附件中的gl-matrix-min.js即可。这里给大家演示一下gl-matrix的基本用法,详细的可以参考官网上的文档:

<div class="km_insert_code" style="text-align: left;">

    // 创建4x4矩阵
    var viewMatrix = mat4.create();

    // 对矩阵进行转置
    mat4.transpose(viewMatrix, viewMatrix);
    // 对矩阵进行求反
    mat4.invert(viewMatrix, viewMatrix);

    // 创建1x3向量
    var positionVector = vec3.create();

    // 对向量进行规范化
    vec3.normalize(positionVector, positionVector);

</div>

有了这些工具,我们就可以开始讲解今天的主题了,使用WebGL绘制三维图形。

二、从2D到3D

在之前的例子中,我只是给大家演示了如何绘制一个二维的矩形,但WebGL真正强大的地方,在于它为我们提供了三维图像的绘制能力。当然这主要的得益于WebGL的计算速度,要知道,绘制三维图形,我们需要进行大量的(逐顶点甚至是逐片元)的矩阵运算,而且这些运算都必须在16ms内完成,才能保证画面的流畅。如果是直接使用Canvas 2D Api绘制三维图像,所有这些运算,只能在CPU中完成。而通过WebGL,这些耗时的运算就可以直接交给GPU,通过GPU中一些专用的硬件,使得运算的过程得到优化(管线,并行)。

说了那么多,那到底我们怎样才能绘制出一个三维图形呢?要绘制出三维图像,我们首先要知道三维图像和二维图像有那些区别。

从上面这幅图,我们可以比较直观的看到一个正方形到立方体的演变过程,主要经历了以下四步:

1、给图像加入深度信息,也就是让这个正方形有了厚度,从一个“面”成为一个“体”

2、换一个角度去观察我们的场景(45度俯瞰),这使得深度信息在视觉上得到了体现

3、光有深度信息还不够,我们观察三维图像一般是带透视的,这样图像更有立体感

4、最后我们需要在场景中加入灯光,灯光下的立方体更加真实

这样我们就有了一个大致的方向,为了绘制三维图形,我们需要一下四部分信息:

<div class="km_insert_code" style="text-align: left;">

    // 获取立方体的顶点数据,包含深度信息(即z轴坐标)
    var modelObject = getCubeVertexData();

    // 获取视图变换矩阵,用来模拟摄像机在不同角度的拍摄
    var viewMatrix = getCameraMatrix();

    // 获取透视变换矩阵,用来模拟现实中近大远小的透视效果
    var projectMatrix = getPerspectiveMatrix();

    // 获取灯光数据,这里得到的是一个点光源,类似白炽灯
    var pointLight = getPositionalLight();

</div>

接下来,我就带着大家一步一步来完成各个方法的功能开发,首先是getCubeVertexData方法:

<div class="km_insert_code" style="text-align: left;">

    function getCubeVertexData() {
        var width = 4,
            height = 4,
            depth = 4;

        var w = width / 2,
            h = height / 2,
            d = depth / 2;

        // 顶点数据,三个坐标(x, y, z)组成一个顶点
        // 每个面有4个点,总共是4x6,24个顶点坐标
        var vertices = new Float32Array([
            -w, h, d,   w, h, d,  -w,-h, d,   w,-h, d, // 0-1-2-3     // front
             w, h,-d,  -w, h,-d,   w,-h,-d,  -w,-h,-d, // 4-5-6-7     // back
            -w, h,-d,  -w, h, d,  -w,-h,-d,  -w,-h, d, // 8-9-10-11   // left
             w, h, d,   w, h,-d,   w,-h, d,   w,-h,-d, // 12-13-14-15 // right
            -w, h,-d,   w, h,-d,  -w, h, d,   w, h, d, // 16-17-18-19 // top
            -w,-h, d,   w,-h, d,  -w,-h,-d,   w,-h,-d  // 20-21-22-23 // bottom
        ]);

        // 法线方向,三个坐标(x, y, z)组成一条法线
        // 例如 [0, 0, 1] 代表指向z轴正方向,长度为1的法线
        var normals = new Float32Array([
             0, 0, 1,   0, 0, 1,   0, 0, 1,   0, 0, 1, // 0-1-2-3     // front 
             0, 0,-1,   0, 0,-1,   0, 0,-1,   0, 0,-1, // 4-5-6-7     // back
            -1, 0, 0,  -1, 0, 0,  -1, 0, 0,  -1, 0, 0, // 8-9-10-11   // left
             1, 0, 0,   1, 0, 0,   1, 0, 0,   1, 0, 0, // 12-13-14-15 // right
             0, 1, 0,   0, 1, 0,   0, 1, 0,   0, 1, 0, // 16-17-18-19 // top
             0,-1, 0,   0,-1, 0,   0,-1, 0,   0,-1, 0  // 20-21-22-23 // bottom
        ]);

        // 顶点下标,WebGL中只能绘制三角形
        // 因此绘制一个面(矩形),需要两个三角形
        // 
        // 0┌──────────┐1
        //  |          |
        //  │          │
        // 2└──────────┘3
        // 
        // 其中 [0, 1, 2] 三个顶点构成第一个三角形
        // 而 [1, 3, 2] 三个顶点构成了第二个三角形
        var indices = new Uint16Array([
             0,  1,  2,  1,  3,  2, // front
             4,  5,  6,  5,  7,  6, // back
             8,  9, 10,  9, 11, 10, // left
            12, 13, 14, 13, 15, 14, // right
            16, 17, 18, 17, 19, 18, // top
            20, 21, 22, 21, 23, 22  // bottom
        ]);

        return { vertices: vertices, normals: normals, indices: indices, size: indices.length };
    }

</div>

从getCubeVertexData方法中,我们获得了与立方体相关的顶点数据,其中包括了顶点坐标vertices,顶点法线方向normals,还有顶点下标indices。其中大家可以注意到,顶点的坐标是包含了z轴坐标,也就是包含了深度信息。有了这些信息,我们就可以进行下一步了,但在继续讲解前,我需要给大家普及一些基本的计算机图形学姿势——矩阵变换。

PG 以下内容涉及三角函数和线性代数,敬请家长注意

1、旋转变换

从上图,已知坐标(x, y),求出绕(0, 0)点旋转弧度b后的坐标(x, y)

我们可以使用矩阵来表示:

2、拉伸变换

已知坐标(x, y),求出绕(0, 0)点向x拉伸s倍,向y方向拉伸t倍后的坐标(x, y)

同样,我们可以使用矩阵来表示:

3、平移变换

已知坐标(x, y),求出向x方向平移s,向y方向平移t后的坐标(x, y)

似乎我们没有办法把它转换成矩阵表示?Too Naive,只要我们引入齐次坐标即可:

通过以上的演示,我们得到了这样一个结论,所有的几何变换都可以转换成这种向量左乘矩阵的形式表示,而且多种变换作用于同一坐标点,只需依次与对应的矩阵左乘即可。

有了以上这些数学姿势,我们就可以继续我们的编码了。

我们先看getCameraMatrix方法,用于获取视图变换矩阵。WebGL绘图都是眼睛(摄像机)在z轴上,向z轴负方向(即屏幕方向)看去产生的视图:

我们并不能改变这个视线的方向。因此,为了能从别的角度来观察场景,我们只能对场景本身进行操作,例如我们要把眼睛从(0, 0, 0)点移动到(0, 0, 10)点,实质上可以通过,把整个场景向z轴负方向移动10来到达相同的效果。也就是说,我们可以通过对场景进行反向的几何变换来模拟眼睛的移动。但如果每一步都需要我们手动的进行反向操作,也未免太麻烦了,为此gl-matrix中提供了mat4.lookAt这样一个方法来辅助我们进行计算:

<div class="km_insert_code" style="text-align: left;">

    function getCameraMatrix() {
        var viewMatrix = mat4.create();

        // 眼睛的位置
        var eye = vec3.fromValues(10, 10, 10);
        // 眼睛所看目标位置
        var center = vec3.fromValues(0, 0, 0);
        // 眼睛向上的方向
        var up = vec3.fromValues(-1, 1, -1);

        mat4.lookAt(viewMatrix, eye, center, up);

        return viewMatrix;
    }

</div>

利用mat4.lookAt方法,我们可以快速的得到眼睛从(10, 10, 10)点,望向(0, 0, 0)点的所需要的反向几何变换矩阵,我们把所得到的矩阵称为视图变换矩阵。

接下来我们看看getPerspectiveMatrix方法,用于获取透视变换矩阵。WebGL绘图的空间,实际为一个1x1x1的单位立方体,而我们眼睛所看到的真实的视觉空间,则是一个四方台:

我们要在WebGL中模拟这种透视,实际就是把这个四方台变换到WebGL的单位立方体上,只要是变换,我们都可以使用矩阵来表示,当然这其中的数学推导我(wo)就(ye)不(bu)说(dong)了,gl-mtraix给我们提供了mat4.perspective方法,来帮助我们计算出这个透视变换矩阵:

<div class="km_insert_code" style="text-align: left;">

    function getPerspectiveMatrix() {
        var projectMatrix = mat4.create();

        // 视场角45度,宽高比为1,最近的平面为z等于0.1,最远的平面为z等于1000
        mat4.perspective(projectMatrix, 45, 1, 0.1, 1000);

        return projectMatrix;
    }

</div>

最后,调用getPositionalLight,来得到灯光信息。这里我们模拟的是一个点光源,与点光源相关的信息,只有两个,第一个是光源的颜色,另一个是光源的位置:

<div class="km_insert_code" style="text-align: left;">

    function getDirectionalLight() {
        // 点光源的颜色,白色,带点灰
        var color = vec3.fromValues(0.7, 0.7, 0.7);
        // 点光源的位置,坐标(-10, 5, 10)
        var position = vec3.fromValues(-10, 5, 10);

        return { color: color, position: position };
    }

</div>

三、3D世界

来到这里我们终于集齐7颗龙珠,可以召唤出神龙了!!!!!

好吧,其实还不可以,我们只是拥有了用于绘制的数据,但怎么绘制我们还不知道(神龙:怪我咯)

我们之前说过,要教会WebGL绘图,我们需要着色器。着色器其实是GPU提供给我们的可编程接口,用于对GPU的管线进行编程,使得GPU能完成我们所需的渲染需求。着色器程序写得好,你就等于成为了上帝,上帝说要有水,给你(http://www.html5tricks.com/demo/webgl-water/index.html),上帝说要有风,拿去(http://www.bongiovi.tw/experiments/webgl/blossom/)

我们不需要弄这么复杂,只要有钱,不,只要一个立方体就可以了:

顶点着色器

<div class="km_insert_code">

    attribute vec4 a_VertexPosition;
    attribute vec4 a_VertexNormal;
    uniform mat4 u_ProjectMatrix;
    uniform mat4 u_ViewMatrix;
    uniform mat4 u_NormalMatrix;
    varying vec3 v_VertexPosition;
    varying vec3 v_VertexNormal;

    void main() {
        vec4 vertexPosition =  u_ViewMatrix * a_VertexPosition;
        vec4 vertexNormal = u_NormalMatrix * a_VertexNormal;

        v_VertexPosition = vertexPosition.xyz;
        v_VertexNormal = vertexNormal.xyz;

        gl_Position = u_ProjectMatrix * vertexPosition;
    }

</div>

片元着色器

<div class="km_insert_code">

    precision mediump float;
    varying vec3 v_VertexPosition;
    varying vec3 v_VertexNormal;
    uniform vec3 u_Color;
    uniform vec3 u_LightColor;
    uniform vec3 u_LightPosition;

    void main() {
        vec3 direction = normalize(u_LightPosition - v_VertexPosition);
        vec3 normal = normalize(v_VertexNormal);

        vec3 color = u_LightColor * u_Color * max(dot(direction, normal), 0.0);

        gl_FragColor = vec4(color, 1.0);
    }

</div>

鉴于篇幅的关系,这次我就先不解析这两个着色器的意思,有兴趣的同学可以rtx我。

有了着色器,我们就利用gl-core提供给我们的方法,生成着色器程序,把数据写于缓冲区,最终绘制我们想要的立方体:

<div class="km_insert_code">

    // 创建着色器程序
    var program = new Program(gl);

    // 绑定顶点着色器
    program.attach(VERTEX_SHADER_SOURCE, gl.VERTEX_SHADER);
    // 绑定片元着色器
    program.attach(FRAGMENT_SHADER_SOURCE, gl.FRAGMENT_SHADER);
    program.link();
    program.bind();

    // 创建顶点坐标缓存区
    var vertexBuffer = new Buffer(gl, gl.ARRAY_BUFFER);
    // 写入顶点坐标数据
    vertexBuffer.write(modelObject.vertices, gl.STATIC_DRAW);
    vertexBuffer.bind(program.attribs.a_VertexPosition, 3, gl.FLOAT);

    // 创建顶点法线缓冲区
    var normalBuffer = new Buffer(gl, gl.ARRAY_BUFFER);
    // 写入顶点法线数据
    normalBuffer.write(modelObject.normals, gl.STATIC_DRAW);
    normalBuffer.bind(program.attribs.a_VertexNormal, 3, gl.FLOAT);

    // 创建顶点下标缓存区
    var indexBuffer = new Buffer(gl, gl.ELEMENT_ARRAY_BUFFER);
    // 写入顶点下标数据
    indexBuffer.write(modelObject.indices, gl.STATIC_DRAW);
    indexBuffer.bind();

    // 写入透视变换矩阵
    gl.uniformMatrix4fv(program.uniforms.u_ProjectMatrix, false, projectMatrix);
    // 写入视图变换矩阵
    gl.uniformMatrix4fv(program.uniforms.u_ViewMatrix, false, viewMatrix);
    // 写入法线变换矩阵
    gl.uniformMatrix4fv(program.uniforms.u_NormalMatrix, false, normalMatrix);
    // 写入立方体颜色
    gl.uniform3f(program.uniforms.u_Color, 1.0, 0.0, 0.0);
    // 写入灯光颜色
    gl.uniform3fv(program.uniforms.u_LightColor, pointLight.color);
    // 写入灯光位置
    gl.uniform3fv(program.uniforms.u_LightPosition, pointLight.position);

    // 清除color buffer和depth buffer中的数据
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    // 绘制
    gl.drawElements(gl.TRIANGLES, modelObject.size, gl.UNSIGNED_SHORT, 0);

</div>

大功告成!!!!

转载地址:https://cloud.tencent.com/developer/article/1005103

QMK固件OLED显示屏配置教程:从零开始实现个性化键盘显示(实操部分) 本教程详细介绍了如何从零开始配置QMK固件的OLED显示屏,实现个性化键盘显示。首先,文章解释了OLED显示屏的基本概念及其在键盘中的应用,并介绍了I2C和SPI两种通信方式。接着,教程逐步指导用户如何在QMK固件中启用OLED功能,包括在rules.mk中启用OLED、在halconf.h和mcuconf.h中配置I2C功能,以及在config.h中设置I2C和OLED参数。最后,教程展示了如何在keymap.c中编写代码,实现OLED显示内容,并提供了进阶定制功能,如显示当前层信息、按键状态和QMK L 阅读详情

相关推荐

ADC INL&DNL测试方法和实例

本文介绍了一种可操作的ADC INL和DNL的测试方法--直方图法(也称码密度法)。并实际使用该方法测试了两款芯片的ADC INL和DNL

APTCHIP的博客 1万+

图形学介绍-3D转换

学习图形学过程中看到来自Hobart and William Smith Colleges的David J. Eck教授编写的图形学介绍V1.3.0,读起来确实有不少的感悟。 第7.1节 3D 转换 我们已经在第 6 章看到了如何使用 WebGL 绘制图元,以及如何实现 2D 转换。 在 3D 中绘制图元是相同的,只是每个顶点有三个坐标而不是两个。 3D 中的转换也类似于 2D,但对于转换而言,第三个维度带来的复杂性增加是可观的。 本节介绍使用 WebGL 的 3D 图形的几何方面。 在下一节中,我们

m0_37206001的博客 1489

从零开始:用ADS仿真设计一个2.4GHz Wi-Fi低噪声放大器(含完整电路图)

本文提供了一份详细的ADS软件仿真指南,手把手教你从零开始设计一个2.4GHz Wi-Fi低噪声放大器。内容涵盖核心指标理解、晶体管选型与建模、匹配网络设计、偏置电路集成,并通过S参数仿真、噪声优化及线性度验证等步骤,最终呈现完整的优化电路图,助力射频初学者掌握LNA设计全流程。

weixin_29197835的博客 799

WebGL绘制三角形

WebGL绘制一个三角形

bb_111的博客 577

STM32 Modbus-RTU从零到实战:手把手教你用HAL库实现工业通信(附完整代码)

本文详细介绍了如何使用STM32 HAL库从零开始实现Modbus-RTU从机通信。内容涵盖RS485硬件设计、CubeMX串口与定时器配置、基于空闲中断的高效数据接收、协议栈状态机设计、CRC16校验实现以及常用功能码处理。文章提供了完整的代码框架和调试方法,帮助开发者快速构建稳定的工业通信节点。

weixin_28278377的博客 184

手把手教你用UC3844设计多路输出反激电源(附PCB布局避坑指南)

本文详细介绍了使用UC3844设计多路输出反激电源的实战技巧,包括核心电路设计、变压器参数计算、PCB布局优化及EMI抑制方法。通过实验室实测数据和项目经验,帮助工程师避开常见设计陷阱,提升电源性能和可靠性。特别附赠PCB布局避坑指南,助力高效完成开关电源设计。

weixin_30300225的博客 565

unigine 三维旋转矩阵(mat3,quat) scale translate 变换矩阵(mat4) 和forward up right 关系 normal binormal tangent

三维中旋转矩阵可以用mat3或quat表示。 两者可以转换。在数学上,旋转和反射对应线代中的正交变换。每行(或每列)相互正交的矩阵且每行(或每列)模长为1,叫正交矩阵。 unigine中是右手坐标系。顺时针方向的角度为正,逆时针方向角度为负 知道y,z 求x:cross(y,z);(trick:将所求的轴朝向自己的反方向,顺时针代入已知的轴,只是在求轴的时候从这个视角,理解旋转的时候需要让轴朝...

qiushangren的专栏 8655

基于YOLOv8深度学习的火焰与烟雾检测系统详解:UI界面 + YOLOv8 + 数据集的实现

通过自动化检测火焰和烟雾,可以提高响应速度,减少潜在的火灾损失,保障人身和财产安全。此外,应用还会显示标记了检测框的视频画面,方便用户直观了解检测效果。同时,前端界面将使用Streamlit来实现,因其可以快速搭建交互式应用,适合我们的需求。要训练一个有效的火焰和烟雾检测模型,我们需要一个包含火焰和烟雾图片的数据集。为了保证模型的准确性和泛化能力,建议收集至少500张火焰和烟雾的图片,保证数据的多样性和代表性。训练过程中,模型会输出每个Epoch的训练损失和验证准确率,便于我们监控模型的学习情况。

YOLO 1317

gl-matrix中lookAt的作用

参考链接:这里 WebGL绘图都是眼睛(摄像机)在z轴上,向z轴负方向(即屏幕方向)看去产生的视图: 我们并不能改变这个视线的方向。因此,为了能从别的角度来观察场景,我们只能对场景本身进行操作,例如我们要把眼睛从(0, 0, 0)点移动到(0, 0, 10)点,实质上可以通过,把整个场景向z轴负方向移动10来到达相同的效果。也就是说,我们可以通过对场景进行反向的几何变换来模拟眼睛的移动。但...

gaidandan的专栏 3605

【高级】系统架构师 | 2026年上半年案例分析真题

标准答案:系统因缺乏足够历史数据(用户行为、物品信息或评分等),难以做出准确推荐的问题。另外两种:物品冷启动(新课程 / 新知识点缺少互动数据)系统冷启动(平台上线初期整体数据稀缺)类型典型表现常见缓解用户冷启动新注册学员无历史问卷/前测、热门兜底、人口统计学特征、知识图谱前置测评物品冷启动新课无人学无人评内容特征推荐、专家标注、探索流量系统冷启动新平台双边都稀缺规则引擎、运营冷启、知识图谱强约束路径本题已点明「用户冷启动」,另外两种按推荐系统经典三分法作答即可。

大胆尝试,小心实践 353

【100%通过率】华为od机试C卷【小朋友来自多少小区】JS 实现

幼儿园组织活动,老师布置了一个任务:每个小朋友去了解与自己同一个小区的小朋友还有几个.我们将这些数量汇总到数组 garden 中。请根据这些小朋友给出的信息,计算班级小朋友至少来自几个小区?

MISAYAONE的博客 1996

【笔记】《WebGL编程指南》学习(3)

WebGL编程指南学习(3),界明城,2022-3-3 3. 再来一点点数学 关于视点,除了Viewpoint-LookAt-UpDirection之外,还有更多需要考虑的东西,比如视场,比如深度 3.1 可视范围(Orthographic) 类似人眼,在渲染场景的时候,定义了可视空间(view volume) 3.1.1 可视空间 两类常用的可视空间:长方体可视空间,由**正射投影(orthographic projection)产生;四棱锥可视空间,由透视投影(perspective projectio

饮冰室 510

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

WEBGL看完你就会了(16)---进入三维世界

摘要:本文介绍了三维空间中的视角变换原理,通过WebGL实现了一个简单的三维场景视图控制。文章首先解释了视点、视线、目标点和上方向等基本概念,阐述了视图矩阵的作用。采用"观察者移动"与"物体移动"的等价性原理,推导了顶点坐标变换公式,并提供了两种着色器代码实现方案。最后通过示例代码展示了如何创建三维三角形场景,并实现键盘控制观察者X坐标移动的功能,演示了视角变换的实际应用效果。

简单Cere 330

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

WebGL编程指南 - 进入三维世界1

初步了解三维呈现方式:视点、观察点、上方向。 了解WebGL可视空间,采用投影矩阵对物体进行投影操作,实现盒状可视空间和正射投影。对于正射投影矩阵的数学原理进行了本书之外的补充说明。 透视投影可视空间、投影矩阵和模型视图投影矩阵的相关操作,提及规范立方体。

zaizai1007的博客 782

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

WebGL 进入三维世界

1.观察目标点和上方向     为了确定观察者的状态,你需要获取两项信息:视点,即观察者的位置;观察目标点(look-at point),即被观察目标所在的点,它可以用来确定视线。此外,因为我们需要把观察到的景象绘制到屏幕上,还需要知道上方向(up direction)。有了这三项信息,就可以确定观察者的状态了。     视点:观察者所在的三维空间中位置,视线的起点。视点坐标一般用(eyeX, ...

weixin_33769207的博客 563

webgl_进入三维世界(1)

激动的心颤抖的手,今天就开始三维空间的学习。 首先我们就从最简单的立方体开始分析吧; 立方体由三角形构成 首先我们要明白三维物体也是由二维图形(特别是三角形)组成的。如图所示,12个三角形组成了一个立方体。 那么我们可能就想,既然三维物体是由三角形组成的,那只需逐个绘制组成物体的每个三角形,最终就可以绘制出整个三维物体了。但是,三维与二维还有一个显著区别;在绘制二维图形时,只需要考虑顶点的x和y坐标,而绘制三维物体时,还得考虑它们的深度信息(也就是z轴)。其次在三维空间站会有视点和视线的概念。你可以理解成

静儿的博客 258

【《WebGL编程指南》读书笔记-进入三维世界(上)】

本文为《WebGL编程指南》读书笔记,第七章进入三维世界的上半部分。 主要要点包括:1.三维的呈现方式:视点、观察点、视线和上方向;2.WebGL可视空间与投影操作,使用盒状可视空间和正射投影进行简单绘图,对正射投影矩阵的数学原理进行了本书之外的补充;3. 透视投影可视空间、投影矩阵和模型视图投影矩阵的相关操作,提及规范立方体。

floating_heart的博客 943

webgl_进入三维世界(2)

显示生活中,我们经常遇到两个物体一前一后放在桌子上,观察时,前面的物体会把后面的物体遮住一部分的情况。 隐藏面消除 为了解决上述问题,WebGL提供了隐藏面消除功能。让我们绘制场景而不必顾及各物体在缓冲区中的顺序,因为那些远处的物体会自动被近处的物体挡住,不会被绘制出来。 开启隐藏面消除功能,需要遵循以下两步: 1.开启隐藏面消除功能。(gl.enable (gl. DEPTH_TEST); 2.在绘制之前,清除深度缓冲区。(gl.clear (gl.DEPTH_BUFEER_BIT); 深度冲突 当几何

静儿的博客 235

webgl——进入三维世界(模型矩阵、视图矩阵、投影矩阵)(六)

文章目录前言一、视点和视线二、投影矩阵 前言 本篇继续前面文章来讲解投影矩阵相关内容。 一、视点和视线 二、投影矩阵

jiegiser博客 2163

【《WebGL编程指南》读书笔记-进入三维世界(下)】

本文为读书笔记第七章下半部分 主要包括以下内容:1. 开启深度检测,使用深度缓冲区进行隐藏面消除,处理物体前后关系;2. 深度冲突的产生条件和解决方案(多边形偏移);3. 通过顶点索引绘制图形。

floating_heart的博客 620

WebGL编程指南(5)进入三维世界

书本源代码 https://download.csdn.net/download/qfire/103710555.1 视点、观察目标点和上方向      我们可以用上述三个矢量创建一个视图矩阵,然后将该矩阵传给顶点着色器。视图矩阵可以表示观察者的状态,含有观察者的视点、观察目标点、上方向等信息。Matrix4.setLookAt()函数可以根据上述三个矢量来创建出视图矩阵。ch07/LookAtT...

Just for fun的专栏 347

【笔记】《WebGL编程指南》学习-第7章进入三维世界(2-可视范围)

可视范围(正射类型)

努力的V崽兽 1064

【笔记】《WebGL编程指南》学习-第7章进入三维世界(4-前后关系)

正确处理对象的前后关系

努力的V崽兽 506

【笔记】《WebGL编程指南》学习-第7章进入三维世界(5-立方体)

彩色立方体

努力的V崽兽 1085

【笔记】《WebGL编程指南》学习-第7章进入三维世界(1-视点和视线)

以用户视角进入三维世界

努力的V崽兽 758

【笔记】《WebGL编程指南》学习-第7章进入三维世界(3-可视空间)

可视空间(正视投影)

努力的V崽兽 688
上一篇: 图解WebGL&Three.js工作原理
下一篇: 计算机视觉新手入门:大佬推荐我这样学习
hsany330
博客等级 码龄20年 388粉丝 42原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值