WebGL之让目标动起来

在此示例中,我们实际上将旋转正方形平面。

使正方形旋转

让我们开始旋转正方形。我们需要的第一件事是创建一个变量,用于跟踪正方形的当前旋转:

var squareRotation = 0.0;

现在我们需要更新drawScene()函数以在绘制正方形时将当前旋转应用于正方形。转换为正方形的初始绘图位置后,我们像这样应用旋转:

mat4.rotate(modelViewMatrix, // destination matrixmodelViewMatrix, // matrix to rotatesquareRotation, // amount to rotate in radians[0, 0, 1],
); // axis to rotate around

这会将 modelViewMatrix 的当前值squareRotation绕 Z 轴旋转。

要进行动画制作,我们需要添加squareRotation随时间更改值的代码。为此,我们可以创建一个新变量来跟踪上次动画播放的时间(我们称之为then),然后将以下代码添加到主函数的末尾

var then = 0;// Draw the scene repeatedly
function render(now) {now *= 0.001; // convert to secondsconst deltaTime = now - then;then = now;drawScene(gl, programInfo, buffers, deltaTime);requestAnimationFrame(render);
}
requestAnimationFrame(render);

该代码用于 requestAnimationFrame 要求浏览器在每一帧上调用函数“render”。requestAnimationFrame 自页面加载以来经过的时间(以毫秒为单位)。我们将其转换为秒,然后从中减去,以计算 deltaTime 自渲染最后一帧以来的秒数。在 drawscene 的结尾,我们添加了要更新的代码 squareRotation。

squareRotation += deltaTime;

源码如下:

// webgl-demo.js
import { initBuffers } from "./init-buffers.js";
import { drawScene } from "./draw-scene.js";let squareRotation = 0.0;
let deltaTime = 0;main();//
// start here
//
function main() {const canvas = document.querySelector("#glcanvas");// Initialize the GL contextconst gl = canvas.getContext("webgl");// Only continue if WebGL is available and workingif (gl === null) {alert("Unable to initialize WebGL. Your browser or machine may not support it.");return;}// Set clear color to black, fully opaquegl.clearColor(0.0, 0.0, 0.0, 1.0);// Clear the color buffer with specified clear colorgl.clear(gl.COLOR_BUFFER_BIT);// Vertex shader programconst vsSource = `attribute vec4 aVertexPosition;attribute vec4 aVertexColor;uniform mat4 uModelViewMatrix;uniform mat4 uProjectionMatrix;varying lowp vec4 vColor;void main(void) {gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;vColor = aVertexColor;}`;// Fragment shader programconst fsSource = `varying lowp vec4 vColor;void main(void) {gl_FragColor = vColor;}`;// Initialize a shader program; this is where all the lighting// for the vertices and so forth is established.const shaderProgram = initShaderProgram(gl, vsSource, fsSource);// Collect all the info needed to use the shader program.// Look up which attributes our shader program is using// for aVertexPosition, aVertexColor and also// look up uniform locations.const programInfo = {program: shaderProgram,attribLocations: {vertexPosition: gl.getAttribLocation(shaderProgram, "aVertexPosition"),vertexColor: gl.getAttribLocation(shaderProgram, "aVertexColor"),},uniformLocations: {projectionMatrix: gl.getUniformLocation(shaderProgram,"uProjectionMatrix"),modelViewMatrix: gl.getUniformLocation(shaderProgram, "uModelViewMatrix"),},};// Here's where we call the routine that builds all the// objects we'll be drawing.const buffers = initBuffers(gl);let then = 0;// Draw the scene repeatedlyfunction render(now) {now *= 0.001; // convert to secondsdeltaTime = now - then;then = now;drawScene(gl, programInfo, buffers, squareRotation);squareRotation += deltaTime;requestAnimationFrame(render);}requestAnimationFrame(render);
}//
// Initialize a shader program, so WebGL knows how to draw our data
//
function initShaderProgram(gl, vsSource, fsSource) {const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);// Create the shader programconst shaderProgram = gl.createProgram();gl.attachShader(shaderProgram, vertexShader);gl.attachShader(shaderProgram, fragmentShader);gl.linkProgram(shaderProgram);// If creating the shader program failed, alertif (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {alert(`Unable to initialize the shader program: ${gl.getProgramInfoLog(shaderProgram)}`);return null;}return shaderProgram;
}//
// creates a shader of the given type, uploads the source and
// compiles it.
//
function loadShader(gl, type, source) {const shader = gl.createShader(type);// Send the source to the shader objectgl.shaderSource(shader, source);// Compile the shader programgl.compileShader(shader);// See if it compiled successfullyif (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {alert(`An error occurred compiling the shaders: ${gl.getShaderInfoLog(shader)}`);gl.deleteShader(shader);return null;}return shader;
}
// draw-scene.js
function drawScene(gl, programInfo, buffers, squareRotation) {gl.clearColor(0.0, 0.0, 0.0, 1.0); // Clear to black, fully opaquegl.clearDepth(1.0); // Clear everythinggl.enable(gl.DEPTH_TEST); // Enable depth testinggl.depthFunc(gl.LEQUAL); // Near things obscure far things// Clear the canvas before we start drawing on it.gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);// Create a perspective matrix, a special matrix that is// used to simulate the distortion of perspective in a camera.// Our field of view is 45 degrees, with a width/height// ratio that matches the display size of the canvas// and we only want to see objects between 0.1 units// and 100 units away from the camera.const fieldOfView = (45 * Math.PI) / 180; // in radiansconst aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;const zNear = 0.1;const zFar = 100.0;const projectionMatrix = mat4.create();// note: glmatrix.js always has the first argument// as the destination to receive the result.mat4.perspective(projectionMatrix, fieldOfView, aspect, zNear, zFar);// Set the drawing position to the "identity" point, which is// the center of the scene.const modelViewMatrix = mat4.create();// Now move the drawing position a bit to where we want to// start drawing the square.mat4.translate(modelViewMatrix, // destination matrixmodelViewMatrix, // matrix to translate[-0.0, 0.0, -6.0]); // amount to translate// 关键数据mat4.rotate(modelViewMatrix, // destination matrixmodelViewMatrix, // matrix to rotatesquareRotation, // amount to rotate in radians[0, 0, 1]);// Tell WebGL how to pull out the positions from the position// buffer into the vertexPosition attribute.setPositionAttribute(gl, buffers, programInfo);setColorAttribute(gl, buffers, programInfo);// Tell WebGL to use our program when drawinggl.useProgram(programInfo.program);// Set the shader uniformsgl.uniformMatrix4fv(programInfo.uniformLocations.projectionMatrix,false,projectionMatrix);gl.uniformMatrix4fv(programInfo.uniformLocations.modelViewMatrix,false,modelViewMatrix);{const offset = 0;const vertexCount = 4;gl.drawArrays(gl.TRIANGLE_STRIP, offset, vertexCount);}
}// Tell WebGL how to pull out the positions from the position
// buffer into the vertexPosition attribute.
function setPositionAttribute(gl, buffers, programInfo) {const numComponents = 2; // pull out 2 values per iterationconst type = gl.FLOAT; // the data in the buffer is 32bit floatsconst normalize = false; // don't normalizeconst stride = 0; // how many bytes to get from one set of values to the next// 0 = use type and numComponents aboveconst offset = 0; // how many bytes inside the buffer to start fromgl.bindBuffer(gl.ARRAY_BUFFER, buffers.position);gl.vertexAttribPointer(programInfo.attribLocations.vertexPosition,numComponents,type,normalize,stride,offset);gl.enableVertexAttribArray(programInfo.attribLocations.vertexPosition);
}// Tell WebGL how to pull out the colors from the color buffer
// into the vertexColor attribute.
function setColorAttribute(gl, buffers, programInfo) {const numComponents = 4;const type = gl.FLOAT;const normalize = false;const stride = 0;const offset = 0;gl.bindBuffer(gl.ARRAY_BUFFER, buffers.color);gl.vertexAttribPointer(programInfo.attribLocations.vertexColor,numComponents,type,normalize,stride,offset);gl.enableVertexAttribArray(programInfo.attribLocations.vertexColor);
}export { drawScene };

WebGL 应用程序中的 mat4.rotate 函数对模型视图矩阵(modelViewMatrix)进行旋转操作。下面是这段代码的详细解释:

  • mat4.rotate(out, a, rad, axis)
    • out:表示结果存储的目标矩阵,即进行旋转操作后的矩阵将存储在这里。
    • a:表示要进行旋转操作的原始矩阵,即待旋转的矩阵。
    • rad:表示旋转的角度,以弧度为单位。
    • axis:表示一个包含 x、y 和 z 分量的数组,指定了旋转的轴向量。

在这段代码中,mat4.rotate 函数的作用是将模型视图矩阵 modelViewMatrix 绕指定的轴进行旋转。具体解释如下:

  • modelViewMatrix 是一个 4x4 的矩阵,用于表示模型在世界坐标系中的位置和方向。
  • modelViewMatrix 同时作为目标矩阵和原始矩阵,表示结果将存储在这个矩阵中,同时也是待旋转的矩阵。
  • squareRotation 是旋转的角度,以弧度为单位,表示要围绕指定轴旋转的角度。
  • [0, 0, 1] 是一个包含 x、y 和 z 分量的数组,表示绕 z 轴旋转。在这种情况下,表示围绕 z 轴顺时针旋转。

因此,这段代码的作用是将模型视图矩阵 modelViewMatrix 绕世界坐标系中的 z 轴进行顺时针旋转,旋转角度为 squareRotation 所指定的弧度值。

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

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

相关文章

备份 ChatGPT 的聊天纪录

备份 ChatGPT 的聊天纪录 ChatGPT 在前阵子发生了不少次对话纪录消失的情况,让许多用户觉得困扰不已,也担心自己想留存的聊天记录消失不见。 好消息是,OpenAI 在 2023 年 4 月 11 日推出了 ChatGPT 聊天记录备份功能,无论是免费…

QT绑定信号槽重载

qt5中信号和槽的绑定方式发生了变化不再使用宏SIGNAL、SLOT而是使用传递函数指针的形式&#xff0c;这时如果遇到重载函数就需要进行一下类型转换&#xff0c;有两种方式 connect(a, QOverload<type>::of(&A::fun), this, &B::fun); connect(a, static_cast&l…

Redis什么这么快和Redis单线程模型和多线程

概述 1、完全基于内存&#xff0c;绝大部分请求是纯粹的内存操作&#xff0c;非常快速。数据存在内存中&#xff0c;类似于HashMap&#xff0c;HashMap的优势就是查找和操作的时间复杂度都是O(1)&#xff1b; 2、数据结构简单&#xff0c;对数据操作也简单&#xff0c;Redis中…

二叉树入门

这篇博客通过手动创建的一个简单二叉树&#xff0c;实现二叉树遍历&#xff0c;返回节点&#xff0c;叶子个数&#xff0c;查找结点等相关操作。 1. 二叉树的概念 二叉树不为空时&#xff0c;由根节点&#xff0c;左/右子树组成&#xff0c;逻辑结构如下&#xff0c;当二叉树…

Postman(注册,使用,作用)【详解】

目录 一、Postman 1. Postman介绍 2. 安装Postman 3. 注册帐号再使用(可保存测试记录) 4. 创建workspace 5. 测试并保存测试记录 一、Postman postman工具可以发送不同方式的请求,浏览器只能发送get请求(所有用这个工具) 在前后端分离开发模式下&#xff0c;前端技术人员…

Spring Boot中SQL语句报错

报错原因&#xff1a; You have an error in your SQL syntax 你的SQL语句出现错误 报错位置&#xff1a; check the manual that corresponds to your MySQL server version for the right syntax to use near :/sql/schema.sql.t_film at line 1 在:/sql/schema.sql附近使用…

主网NFT的发布合约

1.什么是nft? NFT:Non-fungible-token 非同质化货币 2.新建suimove项目 使用sui move new 项目名命令新建sui move项目 sui move new nft_qyx项目结构如下: 3.写nft合约 module qyx123::nft{use sui::object::{Self, UID};use sui::transfer;use sui::tx_context::{Sel…

【工具】Raycast – Mac提效工具

引入 以前看到同事们锁屏的时候&#xff0c;不知按了什么键&#xff0c;直接调出这个框&#xff0c;然后输入lock屏幕就锁了。 跟我习惯的按Mac开机键不大一样。个人觉得还是蛮炫酷的&#xff5e; 调研 但是由于之前比较繁忙&#xff0c;这件事其实都忘的差不多了&#xff0…

JVM-垃圾收集底层算法实现

三色标记 背景描述 在并发标记的过程中&#xff0c;因为标记期间应用线程还在继续跑&#xff0c;对象间的引用可能发生变化&#xff0c;多标和漏标的情况就有可能发生。 如何解决上面的问题&#xff1f; 引入“三色标记” 意思就是&#xff0c;把Gcroots可达性分析遍历对象过程…

BUUCTF---[MRCTF2020]你传你呢1

1.题目描述 2.打开题目链接 3.上传shell.jpg文件&#xff0c;显示连接成功&#xff0c;但是用蚁剑连接却连接不上。shell文件内容为 <script languagephp>eval($_REQUEST[cmd]);</script>4.用bp抓包&#xff0c;修改属性 5.需要上传一个.htaccess的文件来把jpg后缀…

调查数据显示,越来越多的企业正在增加对云存储预算

调查数据显示&#xff0c;越来越多的企业正在增加对云存储的使用和预算&#xff0c;以便加速创新进程。根据2024年Wasabi全球云存储指数&#xff0c;超过一半&#xff08;53%&#xff09;的受访者表示其公共云存储开支超出预算&#xff0c;原因主要包括使用的存储容量超过原计划…

[递归、搜索、回溯]----递归

前言 作者&#xff1a;小蜗牛向前冲 专栏&#xff1a;小蜗牛算法之路 专栏介绍&#xff1a;"蜗牛之道&#xff0c;攀登大厂高峰&#xff0c;让我们携手学习算法。在这个专栏中&#xff0c;将涵盖动态规划、贪心算法、回溯等高阶技巧&#xff0c;不定期为你奉上基础数据结构…

【操作系统概念】 第9章:虚拟内存管理

文章目录 0.前言9.1 背景9.2 按需调页9.2.1 基本概念9.2.2 按需调页的性能 9.3 写时复制9.4 页面置换9.4.1 基本页置换9.4.2 FIFO页置换9.4.3 最优(Optimal)置换9.4.4 LRU&#xff08;Least Recently Used&#xff09;页置换9.4.5 近似LRU页置换9.4.6 页缓冲算法 9.5 帧分配9.5…

IOS面试题object-c 21-30

21、简述IOS static 关键字的作用&#xff1f; 函数体内 static 变量的作用范围为该函数体&#xff0c;不同于 auto 变量&#xff0c;该变量的内存只被分配一次&#xff0c; 因此其值在下次调用时仍维持上次的值&#xff1b; 2.在模块内的 static 全局变量可以被模块内所用函数…

react vue 背景挂载机器

问题&#xff1a;项目当中我们有的时候会遇到多个背景图片在一个地方展示的问题 当时项目比较急没有时间做工具函数&#xff0c;被团队优化以后有&#xff0c;时间进行工具函数编写 技术&#xff1a; 插槽 &#xff0c; 和 css 背景 这个还不是最终的状态 背景定位还有两个属性…

linux新一代的RPM软件包管理器dnf

linux新一代的RPM软件包管理器dnf DNF包管理器克服了YUM包管理器的一些瓶颈&#xff0c;提升了包括用户体验&#xff0c;内存占用&#xff0c;依赖分析&#xff0c;运行速度等多方面的内容。DNF使用 RPM, libsolv 和 hawkey 库进行包管理操作。尽管它没有预装在 CentOS 和 RHE…

探索数据结构:单链表的实战指南

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;数据结构与算法 贝蒂的主页&#xff1a;Betty‘s blog 前言 在上一章节中我们讲解了数据结构中的顺序表&#xff0c;知道了顺序…

3.8 动态规划 背包问题

一.01背包 46. 携带研究材料&#xff08;第六期模拟笔试&#xff09; (kamacoder.com) 代码随想录 (programmercarl.com) 携带研究材料: 时间限制&#xff1a;5.000S 空间限制&#xff1a;128MB 题目描述: 小明是一位科学家&#xff0c;他需要参加一场重要的国际科学大会…

2001-2022年上市公司利润表数据

2001-2022年上市公司利润表数据 1、时间&#xff1a;2001.12.31-2022.12.31 2、范围&#xff1a;上市公司 3、指标&#xff1a;证券代码、证券简称、统计截止日期、报表类型、投资收益、其中&#xff1a;对联营企业和合营企业的投资收益、公允价值变动收益、营业利润、其他综…

探讨2024年AI辅助研发的趋势

一、引言 随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;已经成为当今时代最具变革性的技术之一。AI的广泛应用正在重塑各行各业&#xff0c;其中&#xff0c;AI辅助研发作为科技和工业领域的一大创新热点&#xff0c;正引领着研发模式的深刻变革。从医药…