10. WebGPU 旋转变换

这篇具有很好参考价值的文章主要介绍了10. WebGPU 旋转变换。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

单位圆是半径为 1.0 的圆。

下图是一个单位圆。 [注释1]
10. WebGPU 旋转变换

在上图中,当围绕圆拖动蓝色手柄时,X 和 Y 位置会发生变化,代表该点在圆上的位置。且在顶部,Y 为 1,X 为 0。在右侧,X 为 1,Y 为 0。

如果你还记得三年级的基础数学,将某个东西乘以 1,它会保持不变。所以 123 * 1 = 123。很基础,对吧?好吧,一个单位圆,一个半径为 1.0 的圆也是 1 的一种形式。它是一个旋转的 1。所以可以用这个单位圆乘以一些东西,在某种程度上它有点像乘以 1。

我们将从单位圆上的任意点获取 X 和 Y 值,并将顶点位置乘以之前示例中的值。

下边是着色器的修改。

struct Uniforms {
  color: vec4f,
  resolution: vec2f,
  translation: vec2f,
  rotation: vec2f,
};
 
struct Vertex {
  @location(0) position: vec2f,
};
 
struct VSOutput {
  @builtin(position) position: vec4f,
};
 
@group(0) @binding(0) var<uniform> uni: Uniforms;
 
@vertex fn vs(vert: Vertex) -> VSOutput {
  var vsOut: VSOutput;
 
  // Rotate the position
  let rotatedPosition = vec2f(
    vert.position.x * uni.rotation.x - vert.position.y * uni.rotation.y, //here
    vert.position.x * uni.rotation.y + vert.position.y * uni.rotation.x  //here
  );
 
  // Add in the translation
 // let position = vert.position + uni.translation;
  let position = rotatedPosition + uni.translation;
 
  // convert the position from pixels to a 0.0 to 1.0 value
  let zeroToOne = position / uni.resolution;
 
  // convert from 0 <-> 1 to 0 <-> 2
  let zeroToTwo = zeroToOne * 2.0;
 
  // covert from 0 <-> 2 to -1 <-> +1 (clip space)
  let flippedClipSpace = zeroToTwo - 1.0;
 
  // flip Y
  let clipSpace = flippedClipSpace * vec2f(1, -1);
 
  vsOut.position = vec4f(clipSpace, 0.0, 1.0);
  return vsOut;
}

更新了 JavaScript 增加 uniform 的大小。

  // color, resolution, translation
  //const uniformBufferSize = (4 + 2 + 2) * 4;
  // color, resolution, translation, rotation, padding
  const uniformBufferSize = (4 + 2 + 2 + 2) * 4 + 8; //here
  const uniformBuffer = device.createBuffer({
    label: 'uniforms',
    size: uniformBufferSize,
    usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
  });
 
  const uniformValues = new Float32Array(uniformBufferSize / 4);
 
  // offsets to the various uniform values in float32 indices
  const kColorOffset = 0;
  const kResolutionOffset = 4;
  const kTranslationOffset = 6;
  const kRotationOffset = 8; //here
 
  const colorValue = uniformValues.subarray(kColorOffset, kColorOffset + 4);
  const resolutionValue = uniformValues.subarray(kResolutionOffset, kResolutionOffset + 2);
  const translationValue = uniformValues.subarray(kTranslationOffset, kTranslationOffset + 2);
  const rotationValue = uniformValues.subarray(kRotationOffset, kRotationOffset + 2); //here

我们需要UI用于显示。这篇文章不是关于制作 UI 的教程,所以我只打算使用一个。首先是一些 HTML 给 单位圆 一个占位

  <body>
    <canvas></canvas>
    <div id="circle"></div>
  </body>

然后是一些用于定位的 CSS

#circle {
  position: fixed;
  right: 0;
  bottom: 0;
  width: 300px;
  background-color: var(--bg-color);
}

最后是使用它的 JavaScript。

import UnitCircle from './resources/js/unit-circle.js'; //here
 
...
 
  const gui = new GUI();
  gui.onChange(render);
  gui.add(settings.translation, '0', 0, 1000).name('translation.x');
  gui.add(settings.translation, '1', 0, 1000).name('translation.y');
 
  const unitCircle = new UnitCircle(); //here
  document.querySelector('#circle').appendChild(unitCircle.domElement); //here
  unitCircle.onChange(render); //here
 
  function render() {
    ...
 
    // Set the uniform values in our JavaScript side Float32Array
    resolutionValue.set([canvas.width, canvas.height]);
    translationValue.set(settings.translation);
    rotationValue.set([unitCircle.x, unitCircle.y]); //here
 
    // upload the uniform values to the uniform buffer
    device.queue.writeBuffer(uniformBuffer, 0, uniformValues);

下边是显示结果。拖动圆圈上的手柄进行旋转或拖动滑块进行平移。

10. WebGPU 旋转变换

为什么它会起作用?这里用数学解释一下。

rotatedX = a_position.x * u_rotation.x - a_position.y * u_rotation.y;
rotatedY = a_position.x * u_rotation.y + a_position.y * u_rotation.x;

假设有一个矩形并且想要旋转它。在开始旋转之前,右上角位于( 3.0,-9.0)。让我们在单位圆上从 3 点钟方向顺时针 30 度取一个点。
10. WebGPU 旋转变换

上图圆上的位置是x = 0.87, y = 0.50

 3.0 * 0.87 - -9.0 * 0.50 =  7.1
 3.0 * 0.50 + -9.0 * 0.87 = -6.3

这正是它旋转后的地方
10. WebGPU 旋转变换

同样的取顺时针60度
10. WebGPU 旋转变换

圆圈上的位置是 0.87 和 0.50

 3.0 * 0.50 - -9.0 * 0.87 =  9.3
 3.0 * 0.87 + -9.0 * 0.50 = -1.9

可以看到,当顺时针旋转该点时,X 值变大,Y 值变小。如果继续超过 90 度,X 将再次开始变小,而 Y 将开始变大。这种模式会交替轮换。

单位圆上的点还有另一个名字。它们被称为正弦和余弦。所以对于任何给定的角度,可以像这样获取正弦和余弦。

function printSineAndCosineForAnAngle(angleInDegrees) {
  const angleInRadians = angleInDegrees * Math.PI / 180;
  const s = Math.sin(angleInRadians);
  const c = Math.cos(angleInRadians);
  console.log('s =', s, 'c =', c);
}

如果将代码复制并粘贴到 JavaScript 控制台并键入 printSineAndCosignForAngle(30) ,会看到它打印出 s = 0.50 c = 0.87 (注意:我对数字进行了四舍五入)

如果把它们放在一起,可以将顶点位置旋转到想要的任何角度。只需将旋转设置为要旋转到的角度的正弦和余弦。

  ...
  const angleInRadians = angleInDegrees * Math.PI / 180;
  rotation[0] = Math.cos(angleInRadians);
  rotation[1] = Math.sin(angleInRadians);

下边把代码改成只有一个旋转参数。

  const degToRad = d => d * Math.PI / 180;
 
  const settings = {
    translation: [150, 100],
    rotation: degToRad(30),//here
  };
 
  const radToDegOptions = { min: -360, max: 360, step: 1, converters: GUI.converters.radToDeg };
 
  const gui = new GUI();
  gui.onChange(render);
  gui.add(settings.translation, '0', 0, 1000).name('translation.x');
  gui.add(settings.translation, '1', 0, 1000).name('translation.y');
  gui.add(settings, 'rotation', radToDegOptions);
 
 // const unitCircle = new UnitCircle();
 // document.querySelector('#circle').appendChild(unitCircle.domElement);
 // unitCircle.onChange(render);
 
  function render() {
    ...
 
    // Set the uniform values in our JavaScript side Float32Array
    resolutionValue.set([canvas.width, canvas.height]);
    translationValue.set(settings.translation); //here
    // rotationValue.set([unitCircle.x, unitCircle.y]);
    rotationValue.set([
        Math.cos(settings.rotation), //here
        Math.sin(settings.rotation), //here
    ]);

拖动滑块以平移或旋转。

10. WebGPU 旋转变换

我希望这很符合直觉。接下来是一个更简单的。缩放变换。

注释1

什么是弧度(radians)?

弧度是用于圆、旋转和角度的测量单位。就像我们可以以英寸、码、米等为单位测量距离一样,我们可以以度数或弧度来测量角度。

您可能知道公制测量的数学比英制测量的数学更容易。从英寸到英尺,我们除以 12。从英寸到码,我们除以 36。我不了解你,但我无法在脑海中除以 36。使用公制就容易多了。从毫米换算成厘米,我们除以 10。从毫米换算成米,我们除以 1000。我可以在脑海中除以 1000。

弧度与度数相似。角度使数学变得困难。弧度使数学变得简单。一个圆有 360 度,但只有 2π 弧度。所以一整圈是 2π 弧度。半圈是 1π 弧度。 1/4 圈,即 90 度是 1/2π 弧度。所以如果你想将某物旋转 90 度,只需使用 Math.PI * 0.5 。如果你想将其旋转 45 度,请使用 Math.PI * 0.25 等。

如果您开始考虑弧度,几乎所有涉及角度、圆或旋转的数学运算都非常简单。所以试试吧。使用弧度而不是角度,UI 显示除外。

这个单位圆有 +Y 向下以匹配我们的像素空间也是 Y 向下。 WebGPU 的正常剪辑空间是 +Y 向上。在上一篇文章中,我们已经在着色器中翻转了 Y。

原文地址文章来源地址https://www.toymoban.com/news/detail-483671.html

到了这里,关于10. WebGPU 旋转变换的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 定义一个圆类Circle,成员变量:半径 radius;成员方法:构造方法、get和set半径的方法、计算面积和周长的方法。

    (1)定义一个圆类Circle,成员变量:半径 radius;成员方法:构造方法、get和set半径的方法、        计算面积和周长的方法。定义圆柱和圆锥类,定义相应的变量成员和成员方法。使用以上类编         程,输出圆的面积和圆柱、圆锥的体积。

    2024年02月12日
    浏览(36)
  • 仿射变换中的旋转缩放变换矩阵推导

    仿射变换可以将矩阵形状转换为平行四边形。可以挤压形状,但是必须保持两边平行。常见的是旋转、缩放、平移变换。缩放和平移比较简单,本文重点推导旋转缩放变换矩阵。 任意一点 ( x 0 , y 0 ) (x_0,y_0) ( x 0 ​ , y 0 ​ ) 可以看成 ( x 0 , 0 ) (x_0, 0) ( x 0 ​ , 0 ) 向量和 ( 0 ,

    2024年04月24日
    浏览(31)
  • 【计算机图形学】图形变换(平移变换、比例变换、旋转变换、对称变换、错切变换、复合变换)

    一 实验目的 编写图形各种变换的算法 二 实验内容 1 :自行设计基本图案,完成1-5种简单变换 实验结果如下图所示: 图形初始化: 第一次点击左键,实现平移变换:     第二次点击左键,实现比例变换(同时伴有平移变换):   第三次点击左键,实现对称变换(以平行

    2024年02月05日
    浏览(32)
  • 【C++ OpenCV】图像变换:连接、尺寸、翻转、旋转、仿射变换

    目录 图像缩放变换 图像翻转 图像拼接 纵向拼接 横向拼接 图像插值原理 作用 单线性插值 双线性插值的公式 双线性插值的例子 双线性插值的直观展示 意义 仿射变换 图像旋转 实操 一、实现图像旋转 二、根据定义的三个点实现仿射变换,并且求取仿射变换矩阵 源码 src -

    2024年01月18日
    浏览(38)
  • WPF —— 动画旋转变换

    RotateTransform:在二维x-y坐标系统内围绕指定点顺时针旋转某个对象: 在故事板中依赖属性为: RenderTransform.Angle 就是要进行旋转的角度 直接给按钮添加 RenderTransformOrigin=\\\"0.5,0.5\\\" 是中心位置 。值是比例0 和1, TransformGroup 可以支持多个变换 支持平移 也支持旋转 第一个触发类型 第二

    2024年04月10日
    浏览(27)
  • 认识3D旋转变换矩阵

    前文输出了cesium的Rotation变量,一个矩阵;把这矩阵写下来看下; 0.99939     -0.034899    0    0 0.034899    0.99939      0    0    0           0         1    0    0           0         0    1 看一下3D数学的相关描述; 方位和角位移     不能用绝对坐标来描述物体的 位置

    2024年02月06日
    浏览(23)
  • pygame图像变换:缩放、旋转、镜像

    pygame的transform中封装了一些基础的图像处理函数,列表如下 函数 功能 flip 镜像 scale 缩放至新的分辨率 scale_by 根据因子进行缩放 scale2x 专业图像倍增器 rotate 旋转 rotozoom 缩放并旋转 smoothscale 平滑缩放 smoothscale_by 平滑缩放至新的分辨率 chop 获取已删除内部区域的图像的副本

    2024年02月04日
    浏览(31)
  • 【OpenCV】图像变换(缩放、平移、旋转、仿射)

    图像变换是指通过对图像进行缩放、平移、旋转、仿射、透视等变换来改变图像的形状和大小。在本篇博客中,我们将详细介绍OpenCV中的图像变换函数,并提供示例代码以帮助读者更好地理解这些函数的使用方法。 缩放变换是指通过改变图像的大小来改变图像的形状。在Op

    2024年02月07日
    浏览(39)
  • 二维坐标基本变换(平移、旋转、缩放、镜像、阵列)

    诸如图像、模型等的基本变换,实际上都是点坐标的变换,通过矩阵,可以非常方便的达到这个目的。在下文仅介绍二维坐标变换原理。 首先,定义点类如下: 注意,为了形式统一,变换矩阵应统一为3*3阶,同理,对于三维坐标变换矩阵应是4*4阶。关于矩阵的表示,实际上

    2024年02月04日
    浏览(65)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包