webgl图形平移、缩放、旋转

news2024/12/23 17:44:48

文章目录

  • 前言
  • 平移
    • 图示
    • 代码示例
  • 缩放
    • 图示
    • 代码示例
  • 旋转
    • 公式推导
    • 代码示例
  • 总结


前言

在webgl中将图形进行平移、旋转、缩放的操作称为变换仿射变换,图形的仿射变换涉及到顶点位置的修改,通过顶点着色器是比较直接的方式。本文通过着色器实现对webgl图形的仿射变换。


平移

图示

当对图形进行平移时,只要逐顶点的对每个坐标分量进行平移即可,如下图所示。
在这里插入图片描述
一旦理解这一点,操作起来就很简单了,将齐次坐标的对应偏移量Tx和Ty加在顶点坐标的对应分量上,重新赋值给gl_Position即可,这里每帧都让顶点着色器的位置发生变化,并在动画中执行,实现一个简易的运动效果。

代码示例

    let canvas = document.getElementById('canvas');

    // 获取webgl绘图上下文
    const gl = canvas.getContext('webgl');
    if (!gl) {
      throw new Error('WebGL not supported');
    }

    canvas.width = 500;
    canvas.height = 500;
    gl.viewport(0, 0, canvas.width, canvas.height)

    const vertex = `
			attribute vec4 aPosition;
      attribute float aTranslate;
			void main() {
				gl_Position = vec4(aPosition.x + aTranslate, aPosition.y + 0.5 * aTranslate, aPosition.z, 1.0);
				gl_PointSize = 10.0;
			}
		`
    const fragment = `
			precision highp float;
			// uniform vec4 uColor;
			void main(){
				gl_FragColor =vec4(1.0,0.0,0.0,1.0);
			}
		`

    // 创建program
    const program = initShader(gl, vertex, fragment)
    // 获取attribute变量的数据存储位置
    const aPosition = gl.getAttribLocation(program, 'aPosition');
    const aTranslate = gl.getAttribLocation(program, 'aTranslate');
    // 创建缓冲区对象
    const buffer = gl.createBuffer();
    // 绑定缓冲区对象
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    // 传入的数据
    const vertices = new Float32Array([
      -0.7, -0.5,
      -0.9, -0.7,
      -0.5, -0.7
    ])
    // 开辟空间并写入数据
    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)
    // 缓冲区对象分配给attribute变量
    gl.vertexAttribPointer(aPosition, 2, gl.FLOAT, false, 0, 0)
    // 开启attribue缓冲区变量
    gl.enableVertexAttribArray(aPosition)

    let translate = 0

    function animate() {
      console.log('requestAnimationFrame')
      translate += 0.005;
      if (translate > 1) {
        translate = 0
      }
      gl.vertexAttrib1f(aTranslate, translate)

      // 开始绘制
      gl.drawArrays(gl.POINTS, 0, 1)
      requestAnimationFrame(() => animate())
    }

    animate()

在这里插入图片描述

缩放

图示

缩放的原理也很简单,顶点着色器的x和y分量都乘以一个缩放系数即可
在这里插入图片描述

代码示例


    const vertex = `
			attribute vec4 aPosition;
      attribute float aTranslate;
			void main() {
				gl_Position = vec4(aPosition.x * aTranslate, aPosition.y  * aTranslate, aPosition.z, 1.0);
				gl_PointSize = 10.0;
			}
		`
    ···
    ···
    const vertices = new Float32Array([
      -0.2, 0.0, 
      -0.4, -0.2,
      -0.0, -0.2
    ])
   ···
    let translate = 0
    function animate() {
      console.log('requestAnimationFrame')
      translate += 0.005;
      if (translate > 1) {
        translate = 0
      }
      gl.vertexAttrib1f(aTranslate, translate)

      // 开始绘制
      gl.drawArrays(gl.TRIANGLES, 0, 3)
      requestAnimationFrame(() => animate())
    }

    animate()

在这里插入图片描述

旋转

旋转是一个复杂的平移,为了描述旋转动作,需要指定以下三点:

  • 旋转轴
  • 旋转方向
  • 旋转角度

公式推导

假设原本齐次坐标系上一点P的坐标是(x,y,z),经逆时针旋转角度β后移动至P’(x’, y’, z’),如下:
在这里插入图片描述
r表示原点到旋转前的P的距离,α是X轴旋转到P的角度。则P的坐标可以表示为:

  • x = r * cos α
  • y = r * sin α

P’的坐标可表示为:

  • x’ = r * cos (α + β)
  • y’ = r * sin (α + β)

将P’展开得:

  • x’ = r * ( cos α * cos β - sin α * sin β )
  • y’ = r * ( sin α * cos β + cos α * sin β )

最后将P坐标代入上式可得P’与P的对应关系

  • x’ = x * cos β - y * sin β
  • y’ = x * sin β + y * cos β
  • z’ =z

代码示例

为了让绕z轴效果显得更加清晰,我们把三角形的一个顶点放在原点位置并绕Z轴进行旋转操作。
在这里插入图片描述

    const vertex = `
			attribute vec4 aPosition;
      attribute float deg;
			void main() {
				gl_Position.x = aPosition.x * cos(deg) -  aPosition.y * sin(deg);
        gl_Position.y = aPosition.x * sin(deg) +  aPosition.y * cos(deg);
        gl_Position = vec4(gl_Position.x, gl_Position.y, gl_Position.z, 1.0);
				gl_PointSize = 10.0;
			}
		`
    ···
    ···
    const vertices = new Float32Array([
      -0.0, 0.0, 
      -0.2, -0.2,
      0.2, -0.2
    ])
   ···
    let translate = 0
    function animate() {
      console.log('requestAnimationFrame')
      translate += 0.01;
      gl.vertexAttrib1f(deg, translate)

      // 开始绘制
      gl.drawArrays(gl.TRIANGLES, 0, 3)
      requestAnimationFrame(() => animate())
    }

    animate()

在这里插入图片描述

总结

webgl通过操作顶点着色器实现图形的平移,缩放,旋转操作,在接下来将介绍通过转换矩阵来实现这部分功能。

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

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

相关文章

ArcGIS基础实验操作100例--实验65按字段调整点符号方向

本实验专栏参考自汤国安教授《地理信息系统基础实验操作100例》一书 实验平台:ArcGIS 10.6 实验数据:请访问实验1(传送门) 高级编辑篇--实验65 按字段调整点符号方向 目录 一、实验背景 二、实验数据 三、实验步骤 &#xff0…

计算机组成原理_总线

计算机组成原理总目录总线概述 1. 总线介绍 我们知道计算机中有CPU、主存、辅存,以及打印机、键盘、鼠标等等的一些外设 那么各个设备之间肯定是要进行数据传输的,这就需要许多线路将它们连接起来 第一种方法:两两相联 外设数量越多&#xf…

35、基于STM32的电子钟(DS1302)

编号:35 基于STM32的电子钟(DS1302) 功能描述: 本设计由STM32单片机液晶1602按键DS1302时钟组成。 1、采用STM32F103最小系统。 2、利用DS1302芯片提供时钟信号 3、液晶1602实时显示年月日、时分秒、星期等信息。 4、三个按键可…

隐形AR眼镜厂商Mojo Vision裁员75%,专注Micro LED技术

1月7日青亭网报道,隐形AR眼镜厂商Mojo Vision官方宣布了一项重大调整,其中因为产品进展问题,同时还有融资进展受阻等面临大裁员,将进行一系列中心调整,据了解本次裁员比例高达75%。重点关注:1,M…

【Day5】力扣第328题,奇偶链表

前言: 大家好,我是良辰丫🚀🚀🚀,今天带大家刷一个力扣链表题,有人可能会说,一道题够嘛,刚开始刷题别着急,毕竟,心急吃不了热豆腐,&…

Mathorcup数学建模竞赛第六届-【妈妈杯】B题:小区车位分布的评价和优化模型(附特等奖获奖论文和Java代码)

赛题描述 随着现代社会经济的快速发展,房地产成为国家经济发展中重要的经济增长点之一。而小区内汽车停车位的分布对于小区居民的上下班出行影响很大。请建立数学模型,解决下列问题: 问题1:分析评判小区汽车停车位分布是否合理的几个关键指标,建立评判车位分布合理的数学…

嵌入式Linux-对子进程的监控

1. 进程的诞生与终止 1.1 进程的诞生 一个进程可以通过 fork()或 vfork()等系统调用创建一个子进程,一个新的进程就此诞生!事实上,Linux系统下的所有进程都是由其父进程创建而来,譬如在 shell 终端通过命令的方式执行一个程序./…

leetcode 1658. 将 x 减到 0 的最小操作数[python3 双指针实现与思路整理]

题目 给你一个整数数组 nums 和一个整数 x 。每一次操作时,你应当移除数组 nums 最左边或最右边的元素,然后从 x 中减去该元素的值。请注意,需要 修改 数组以供接下来的操作使用。 如果可以将 x 恰好 减到 0 ,返回 最小操作数 &a…

HTML与CSS基础(四)—— CSS基础(选择器进阶、Emmet语法、背景属性、元素显示模式、三大特性)

一、选择器进阶目标:能够理解 复合选择器 的规则,并使用 复合选择器 在 HTML 中选择元素1. 复合选择器1.1 后代选择器:空格作用:根据 HTML 标签的嵌套关系,选择父元素 后代中 满足条件的元素 选择器语法:选…

第二章JavaWeb基础学习路线

文章目录什么是Java WebJava Web基础的技术栈关于我们的客户端与服务端(BS)我们客户端的形式**PC端网页****移动端**服务端应用程序关于请求(request)和响应(response)类比生活中的请求和响应服务器中的请求和响应项目的逻辑构成架…

CSS权威指南(六)文字属性

1.缩进和行内对齐 (1)缩进文本(text-indent) text-indent属性把元素的第一行文本缩进指定的长度,缩进的长度可以可以是负值。这个属性通常用于缩进段落的第一行。text-indent作用于块级元素之上,缩进将沿着…

config:配置中心

Spring Cloud Config 为分布式系统中的外部配置提供服务器端和客户端支持。使用 Config Server,您可以集中管理所有环境中应用程序的外部配置。 Spring Cloud Config就是一个配置中心,所有的服务都可以从配置中心取出配置,而配置中心又可以从…

mmap(内存映射)、sendfile() 与零拷贝技术

内存映射(Memory-mapped I/O)是将磁盘文件的数据映射到内存,用户通过修改内存就能修改磁盘文件。 RocketMQ为什么快?kafka为什么快?什么是mmap?这些问题都逃不过一个点,就是零拷贝。 虽然还有其…

电脑不能开机的几个常见原因

现在手机已经将电脑取代了,用电脑的越来越少,因为一些原因上网课的多了起来,大家都将放置几年的电脑搬了出来,开不开机的大有人在,由于机器闲置很久大多都出现了各种各样的故障和问题,在这里总结了电脑台式…

C语言:浮点型存储方式

浮点型存储方式 任意一个二进制浮点数V可以表示成下面的形式 (-1)^S *M *2^E 1(S符号位) 8(E阶码) 23(M尾码)省略首位1 S:表示正负 只有0/1两个值 M:由浮点数转化成二进制数表示 在…

4.7、IPv4 数据报的首部格式

固定部分:每个 IP 数据报首部都必须包含的内容 某些 IP 数据报的首部除了包含 202020 字节的固定部分外,还包含一些可选的字段来增加 IP 数据报的功能 IP 数据报的首部常以 323232 个比特为单位进行描述 图中的每一行都由 323232 个比特(也…

小波分析——4.使用小波对信号成分进行分析

文章目录首先创建一个包含多频率成分的信号然后我们用数学实现一个墨西哥草帽小波然后我们开始对原始信号进行处理吧接下来可以把信号成分进行绘制在前面的章节里已经介绍过小波的理论、公式等知识点,现在我们来看看如何用小波来实现对复杂信号的成分分析。 在我们…

性能优化系列之『HTML5 离线化:主流的技术实现方案有哪些?』

文章の目录一、离线包类型二、离线包架构三、离线包下载四、离线包运行模式五、大厂离线包方案写在最后一、离线包类型 全局离线包:包含公共的资源,可供多个应用共同使用私有离线包:只可以被某个应用单独使用 二、离线包架构 三、离线包下载…

Fairness in Recommendation: A Survey 阅读笔记

论文链接 搁置了许久的毕设,又要开始重新启航。 2022年的最后一段时间过得真是很崎岖,2023希望大家平安喜乐。 课设还未结束,但是毕设不能再拖,开工啦!这又是一篇综述,有关推荐系统中的公平性,…

5.Isaac教程--创建Isaac应用

创建Isaac应用 本教程将指导您完成使用 Isaac SDK 创建机器人应用程序的过程,以视频输入的 OpenCV 边缘检测处理为例。 文章目录创建Isaac应用预安装显示相机源创建应用程序文件启用节点间通信配置组件创建 Bazel 构建文件运行应用程序查看相机源处理相机源添加边缘…