如何在 webgl 中缩放纹理?

2024-05-05

我有一个尺寸为 800x600 的纹理。如何在 webgl 上缩放它<canvas>以另一个尺寸并保持原始纵横比?假设绘图缓冲区和画布具有相同的尺寸。


鉴于 WebGL 只关心剪辑空间坐标,您只需绘制一个 2 单位四边形(-1 到 +1),并根据画布的方面与图像的方面进行缩放。

换句话说

  const canvasAspect = canvas.clientWidth / canvas.clientHeight;
  const imageAspect = image.width / image.height;

  let scaleY = 1;
  let scaleX = imageAspect / canvasAspect;

请注意,您需要决定如何适合图像。scaleY= 1意味着图像将始终垂直适合,水平适合任何结果。

如果你想让它水平放置,那么你需要使scaleX = 1

  let scaleX = 1;
  let scaleY = canvasAspect / imageAspect;

如果你想要它contain then

  let scaleY = 1;
  let scaleX = imageAspect / canvasAspect;
  if (scaleX > 1) {
    scaleY = 1 / scaleX;
    scaleX = 1;
  }

如果你想要它cover then

  let scaleY = 1;
  let scaleX = imageAspect / canvasAspect;
  if (scaleX < 1) {
    scaleY = 1 / scaleX;
    scaleX = 1;
  }
let scaleMode = 'fitV';

const gl = document.querySelector("canvas").getContext('webgl');
const vs = `
attribute vec4 position;
uniform mat4 u_matrix;
varying vec2 v_texcoord;
void main() {
  gl_Position = u_matrix * position;
  v_texcoord = position.xy * .5 + .5;  // because we know we're using a -1 + 1 quad
}
`;
const fs = `
precision mediump float;
varying vec2 v_texcoord;
uniform sampler2D u_tex;
void main() {
  gl_FragColor = texture2D(u_tex, v_texcoord);
}
`;

let image = { width: 1, height: 1 }; // dummy until loaded
const tex = twgl.createTexture(gl, {
  src: 'https://i.imgur.com/TSiyiJv.jpg',
  crossOrigin: 'anonymous',
}, (err, tex, img) => {
  // called after image as loaded
  image = img;
  render();
});

const programInfo = twgl.createProgramInfo(gl, [vs, fs]);
const bufferInfo = twgl.createBufferInfoFromArrays(gl, {
  position: {
    numComponents: 2,
    data: [
      -1, -1,  // tri 1
       1, -1,
      -1,  1,      
      -1,  1,  // tri 2
       1, -1,
       1,  1,
    ],
  }
});


function render() {
  // this line is not needed if you don't
  // care that the canvas drawing buffer size
  // matches the canvas display size
  twgl.resizeCanvasToDisplaySize(gl.canvas);

  gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
  gl.useProgram(programInfo.program);
  twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);

  const canvasAspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
  const imageAspect = image.width / image.height;
  let scaleX;
  let scaleY;

  switch (scaleMode) {
    case 'fitV':
      scaleY = 1;
      scaleX = imageAspect / canvasAspect;
      break;
    case 'fitH':
      scaleX = 1;
      scaleY = canvasAspect / imageAspect;
      break;
    case 'contain':
      scaleY = 1;
      scaleX = imageAspect / canvasAspect;
      if (scaleX > 1) {
        scaleY = 1 / scaleX;
        scaleX = 1;
      }
      break;
    case 'cover':
      scaleY = 1;
      scaleX = imageAspect / canvasAspect;
      if (scaleX < 1) {
        scaleY = 1 / scaleX;
        scaleX = 1;
      }
      break;
  }
  
  twgl.setUniforms(programInfo, {
    u_matrix: [
      scaleX, 0, 0, 0,
      0, -scaleY, 0, 0,
      0, 0, 1, 0,
      0, 0, 0, 1,
    ],
  });
  gl.drawArrays(gl.TRIANGLES, 0, 6);
}

render();
window.addEventListener('resize', render);
document.querySelectorAll('button').forEach((elem) => {
  elem.addEventListener('click', setScaleMode);
});

function setScaleMode(e) {
 scaleMode = e.target.id;
 render();
}
html, body { 
  margin: 0;
  height: 100%;
}
canvas {
  width: 100%;
  height: 100%;
  display: block;
}
.ui {
  position: absolute;
  left: 0;
  top: 0;
}
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<canvas></canvas>
<div class="ui">
  <button id="fitV">fit vertical</button>
  <button id="fitH">fit horizontal</button>
  <button id="contain">contain</button>
  <button id="cover">cover</button>
</div>

上面的代码使用 4x4 矩阵来应用比例

  gl_Position = u_matrix * position;

它可以很容易地直接通过秤

  uniform vec2 scale;
  ...
  gl_Position = vec4(scale * position.xy, 0, 1);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 webgl 中缩放纹理? 的相关文章

  • 如何使用 numpy 在二维数组上执行最大/平均池化

    给定一个 2D M x N 矩阵和一个 2D 内核 K x L 我如何返回一个矩阵 该矩阵是使用图像上给定内核进行最大或平均池化的结果 如果可能的话我想使用 numpy 注意 M N K L 可以是偶数也可以是奇数 并且它们不需要彼此完全整
  • 从 Android 模拟器使用 WebView WebGL

    据我了解 WebGL 仅在 Android Lollipop 中的 WebView 更新 Play 商店中的 WebView 组件 和较新版本 无需 Play 商店更新 中受支持 但是 我有一个使用 Android 7 1 1 的模拟器 并
  • 如何在R中用随机数填充矩阵?

    expand grid i rexp 5 rate 0 1 它只创建一列 但有什么方法可以轻松地将其乘以 5 列吗 我的意思是 matlab 的做事方式 比如rand exp 0 1 10 20 创建一个指数分布随机数的矩阵 平均值为 0
  • 反转或点 kxnxn 矩阵的快速方法

    有没有一种快速方法可以使用 numpy 计算 kxnxn 矩阵的逆矩阵 在每个 k 切片处计算逆矩阵 换句话说 有没有办法矢量化下面的代码 gt gt gt from numpy linalg import inv gt gt gt a r
  • 为什么 import numpy 不会自动包含 matlib

    我正在尝试使用水平重复 numpy array xa numpy matlib repmat x 1 3 但是 直接输入此内容会导致错误 我必须添加import numpy matlib为了a numpy matlib repmat x 1
  • 2D 矩阵上的 Numpy where()

    我有一个像这样的矩阵 t np array 1 2 3 foo 2 3 4 bar 5 6 7 hello 8 9 1 bar 我想获取行包含字符串 bar 的索引 在一维数组中 rows np where t bar 应该给我索引 0 3
  • WebGL iOS 渲染为浮点纹理

    我正在尝试在 iOS Safari 上的 WebGL 中渲染浮点纹理 而不是在本机应用程序中 我已经设法让 iOS 读取手动 例如从 JavaScript 创建的浮点纹理 但是当我创建浮点类型的帧缓冲区并使用 GPU 渲染到其中时 它不起作
  • 在每次迭代中使用 for 循环的索引命名图像

    我正在使用 MATLAB 进行图像处理项目 我使用 for 循环在每次循环迭代时生成某种图像数据 图像大小不同 我的问题是如何阻止它在下一次迭代中覆盖图像 Img i j data 理想情况下我希望它有 Img 1 data for 1st
  • glm 中矩阵值的顺序不正确?

    我开始使用GLM http glm g truc net通过 OpenGL 3 和 GLSL 进行数学运算的库 我需要正交投影来绘制 2D 图形 所以我编写了这个简单的代码 glm mat4 projection 1 0 projectio
  • 更快地评估从右到左的矩阵乘法

    我注意到以二次形式评估矩阵运算右到左明显快于左到右在 R 中 取决于括号的放置方式 显然它们都执行相同的计算量 我想知道为什么会这样 这与内存分配有什么关系吗 A 5000 5000 B 5000 2 A matrix runif 5000
  • webglcontextcreationerror事件:是否同步触发?

    Is the webglcontextcreationerror 事件 https developer mozilla org en US docs Web Events webglcontextcreationerror同步触发还是异步触
  • numpy.linalg.inv() 是否给出了正确的矩阵逆?编辑:为什么 inv() 给出数值错误?

    我有一个矩阵形状 4000 4000 我想取逆矩阵 我对逆矩阵的直觉因如此大的矩阵而崩溃 起始矩阵的值大小为e 10 具有以下值 print matrix给出一个输出 2 19885119e 10 2 16462810e 10 2 1306
  • 2D 矩阵和重载operator() / 丑陋的语法

    我在我的一个项目中使用二维矩阵 这就像建议的那样C 常见问题精简版 http www parashift com c faq lite operator overloading html faq 13 10 巧妙的是你可以像这样使用它 in
  • MPI - 发送和接收列

    我需要从一个进程发送矩阵列并从另一个进程接收它 我尝试运行以下程序 但得到了一个奇怪的结果 至少我这么认为 仅复制矩阵的第一个元素 某些矩阵元素会发生意外变化 include
  • 如何使用 Julia 查找矩阵中的连通分量

    假设我有以下矩阵 此处用 Julia 语言定义 mat 1 1 0 0 0 1 1 0 0 0 0 0 0 0 1 0 0 0 1 1 将一组值为 1 的相邻元素视为一个 分量 如何识别该矩阵有 2 个分量以及每个分量由哪些顶点组成 对于矩
  • Numpy:查找两个 3-D 数组之间的欧几里德距离

    给定两个维度为 2 2 2 的 3 D 数组 A 0 0 92 92 0 92 0 92 B 0 0 92 0 0 92 92 92 如何有效地找到 A 和 B 中每个向量的欧几里得距离 我尝试过 for 循环 但速度很慢 而且我正在按 g
  • 矩阵循环移位

    有谁知道对矩阵进行右循环移位的有效方法 顺便说一句 矩阵是二元矩阵 但求解非二元矩阵的方法也很好 现在 我正在考虑为矩阵的行实现一个圆形数组 并在需要移位操作时更新每一行 我正在考虑的另一种方法是实现一个指向由向量表示的列 矩阵 的指针向量
  • (C) 获取矩阵中一行的 3 个最小元素,并随机选择一个

    我有一个 8x8 矩阵 在选择我想要的行后 我想获得它的三个最小元素 并随机选择这三个元素之一 问题是我不知道如何处理这三个要素 我只知道如何获取最小元素 即下面的代码 int piezas 8 8 0 2 2 5 3 2 1 1 0 4
  • glClipPlane - webGL 中有等效的吗?

    我有一个 3D 网格 是否有可能像这样呈现剖面图 剪辑 glClipPlane在OpenGL中 我正在使用 Three js r65 我添加的最新着色器是 片段着色器 uniform float time uniform vec2 reso
  • 在 IOS 10 beta 7 (Safari) 中使用 webGL 渲染视频 - 显示奇怪的紫色

    我正在 webGL 中渲染视频 通过传递Video对象作为源texImage2D 这在所有平台 支持 webGL 中都很好用 但是在 IOS 10 beta 7 的 Safari 中 它以奇怪的颜色渲染 在以前的 IOS 版本中看起来还不错

随机推荐

  • ProjectCracker 与 .netstandard 2.0 项目

    我的团队最近从使用 net 框架转向使用 net 标准 2 0 作为我们的 F 库 我们有一些在项目上运行的内部脚本来自动生成 Markdown 文档 这些脚本使用 F 编译器服务 SDK 来分析代码并检索类型元数据 文档注释等 我们正在使
  • 将应用程序状态保存在磁盘或其他位置,以便用户稍后访问它

    In 弹性构建器 4 5我正在做一个像这样的项目cacoo http www cacoo com 我想保存diagrams display object ui components text 在将应用程序关闭到应用程序之后我无法访问的某个地
  • 将 CSV 文件上传到 SQL 服务器

    上传大文件的最佳方式是什么csv使用 C 将数据文件导入 SQL Server 该文件包含大约 30 000 行和 25 列 首先 你不需要编程的东西 您可以使用 SQL 管理工具直接将 CSV 文件上传到 SQL 数据库 但是 如果您确实
  • Android 文件删除在图库中留下空占位符

    我通过以下方式插入图像 ContentValues values new ContentValues values put Images Media TITLE filename values put Images Media DATE A
  • 当每个人都对 OSGi 进行标准化时,为什么 Sun 还要发明另一个模块系统?

    Sun 在 JDK 模块化方面投入了大量精力 其形式为Jigsaw http openjdk java net projects jigsaw 并暗示它也应该成为其他 Java 开发人员选择的模块格式 使用此功能的唯一著名参与者是 NetB
  • 为什么 Solaris 汇编器生成的机器代码与 GNU 汇编器在这里不同?

    我为 amd64 编写了这个小汇编文件 对于这个问题来说 代码的作用并不重要 globl fib fib mov edi ecx xor eax eax jrcxz 1f lea 1 rax ebx 0 add rbx rax xchg r
  • 无法初始化静态QList?

    我收到以下错误 Cube cpp 10 error expected initializer before lt lt token 以下是头文件的重要部分 ifndef CUBE H define CUBE H include
  • ZeroMQ可以用来接受传统的套接字请求吗?

    我正在尝试使用 ZeroMQ 重写我们的旧服务器之一 现在我有以下服务器设置 适用于 Zmq 请求 using var context ZmqContext Create using var server context CreateSoc
  • gensim如何计算doc2vec段落向量

    我正在看这篇论文http cs stanford edu quocle paragraph vector pdf http cs stanford edu quocle paragraph vector pdf 它指出 段落向量和词向量被平
  • ggplot2 使用 geom_line 手动指定颜色

    我正在尝试绘制下面的图表 并想手动指定颜色 我需要按基因型绘制 因为有多个基因型属于同一个 Bgrnd All 并且我希望它们在绘制的线条中单独出现 但是 我想按 Bgrnd All 对线条进行着色 特别是按照我在 scale fill m
  • AutoCompleteTextView 不显示建议

    我正在尝试为 android 创建一个应用程序 我想在其中保留AutoCompleteTextView显示减少用户工作量的建议 目前我正在使用我编写的小代码进行测试 但没有得到建议 我把代码贴出来 请帮我找出错误 public class
  • *_在 Django 模型上设置属性

    我有一个非常基本的问题django db models In this 官方 Django 教程 https docs djangoproject com en 1 4 intro tutorial01 如果您搜索单词 choice set
  • “wget -O”是什么意思?

    我的 shell 脚本中有一个像这样的 wget 命令 reponse wget O http localhost 8080 app index html 我不明白 O 选项 有人向我解释说 O 输出到某个地方 输出到当前流 我在 wget
  • 在 R 中使用 glmnet 和 dotCall64 的长向量

    我使用 glmnet 和 glmnetcr 来拟合序数回归模型 不幸的是 我的模型矩阵约为 640000 5000 这大于可以存储在 32 位整数中的大小 并且我遇到了其他人描述的相同问题 R 向量大小限制 C 中不支持长向量 参数 5 h
  • 正则表达式匹配没有给定前缀的特定字符串

    我需要匹配包含值且没有给定前缀的所有行 例子 我想要包含的所有行word当它没有前缀时prefix So foobar gt no match prefix word gt no match prefix word suffix gt no
  • 查看作为 TFS 中工作项的一部分更改的所有文件的列表

    如果我针对工作项签入代码 则每次签入都会创建一个变更集 我可以查看工作项的链接选项卡 然后查看每个变更集以查看已更改的文件 然而 随着时间的推移 工作项可能最终会产生许多变更集 并且查找所有已更改的文件可能是一个非常耗时且痛苦的过程 有没有
  • 在多个 Compass 项目中加载全局 SASS 文件

    我想创建一个多个 Compass 项目将访问的 SASS 文件目录 该目录将包含许多具有相似样式 表单元素 clearfixes 重置等 的常见元素的 SASS 文件 我希望在多个项目中访问和使用这些元素 如何在多个项目中包含这个全局 SA
  • Kivy pygame错误

    我一直在尝试让 Kivy 在我的 Mac Lion 上运行 但遇到了问题 我按照 Kivy 网站上的说明进行操作 由于 Kivy 1 8 支持 Python 3 所以我想使用 3 3 运行它 最后通过编辑 kivy 文件以指向 3 3 而不
  • 如何使用 Android Studio 2.1.3 从 Android 中的文本文件中获取随机行?

    我有一个 500 行的文本文件 我将此文本文件放置在 app src main assets 文件夹中 名称为 words txt 在此文件中 每一行都用换行符分隔 现在我需要从这个文本文件中获取随机行 在发布此内容之前 我访问了以下问题
  • 如何在 webgl 中缩放纹理?

    我有一个尺寸为 800x600 的纹理 如何在 webgl 上缩放它