WebGL 绘制图像

2024-03-27

我是 WebGL 新手,之前在 Java 中使用过 OpenGL。我一直在尝试编写一个简单的函数,该函数以特定的大小和旋转在特定位置绘制图像。但在网上搜索了一段时间后,我的代码仍然无法运行。

目前,我已经成功绘制了图像,但是该图像距离正确的位置、具有正确的尺寸和旋转还很遥远。我已经失去了对代码的作用和需要的概述,因为我使用了许多不同教程中的代码,因为我没有找到一个包含我所有规范的教程。

我知道图像加载部分肯定有效。我只需要帮助制作一个函数

  • 设置顶点和片段着色器(用于绘制纹理的宽度)
  • 将其平移、调整大小并旋转到正确的位置、大小和旋转
  • 并画出它

有人可以帮我吗?


你也许应该阅读 WebGL http://webglfundamentals.org特别是关于matrices http://webglfundamentals.org/webgl/lessons/webgl-2d-matrices.html.

无论如何,这里是来自 canvas 2d API 的“drawImage”,使用完整的变换堆栈在 WebGL 中重新编写。

换句话说,在 Canvas2D 中你可以这样做

ctx.save();
ctx.translate(x, y);
ctx.rotate(angle);
ctx.scale(w, h);
ctx.drawImage(img, x, y);
ctx.restore();

下面你可以这样做

save();
translate(x, y);
rotate(angle);
scale(w, h);
drawImage(targetWidth, targetHeight, tex, texWidth, texHeight, x, y);
restore();
var m4 = twgl.m4;
var gl = document.getElementById("c").getContext('webgl');
var programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);

// a unit quad
var arrays = {
  position: { 
    numComponents: 2, 
    data: [
      0, 0,  
      1, 0, 
      0, 1, 
      0, 1, 
      1, 0,  
      1, 1,
    ],
  },
};
var bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);
  
// Let's use a 2d canvas for a texture just so we don't have to download anything
var ctx = document.createElement("canvas").getContext("2d");
var w = 128;
var h = 64;
ctx.canvas.width = w;
ctx.canvas.height = h;
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, w, h);
ctx.fillStyle = "green";
ctx.fillRect(w / 8, h / 8, w / 8 * 6, h / 8 * 6);
ctx.fillStyle = "red";
ctx.fillRect(w / 4, h / 4, w / 2, h / 2);
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.font = "20px sans-serif";
ctx.fillStyle = "yellow";
ctx.fillText("texture", w / 2, h / 2);
      
var tex = twgl.createTexture(gl, { src: ctx.canvas });

// Implement a matrix stack like Canvas2d
var matrixStack = [ m4.identity() ];      
      
function render(time) {      
  var t = time * 0.001;

  var texWidth     = w;
  var texHeight    = h;
  var targetWidth  = gl.canvas.width;
  var targetHeight = gl.canvas.height;
      
  save();
  translate(
    (Math.sin(t * 0.9) * 0.5 + 0.5) * targetWidth,
    (Math.sin(t * 0.8) * 0.5 + 0.5) * targetHeight);
  rotate(t * 0.7);
  scale(
    Math.sin(t * 0.7) * 0.5 + 1,
    Math.sin(t * 0.6) * 0.5 + 1);
  
  // scale and rotate from center of image
  translate(texWidth * -0.5, texHeight * -0.5);
    
  drawImage(
    targetWidth, targetHeight,
    tex, texWidth, texHeight,  
    0, 0);
    
  restore();
    
  requestAnimationFrame(render);
}
requestAnimationFrame(render);

function getCurrentMatrix() {
  return matrixStack[matrixStack.length - 1];
}

function save() {
  matrixStack.push(m4.copy(getCurrentMatrix()));
}

function restore() {
  matrixStack.pop();
  if (!matrixStack.length) {
    matrixStack.push(m4.identity());
  }
}

function translate(x, y) {
  var m = getCurrentMatrix();
  m4.translate(m, [x, y, 0], m);
}

function scale(x, y) {
  var m = getCurrentMatrix();
  m4.scale(m, [x, y, 1], m);
}

function rotate(radians) {
  var m = getCurrentMatrix();
  m4.rotateZ(m, radians, m);
}
      

// we pass in texWidth and texHeight because unlike images
// we can't look up the width and height of a texture

// we pass in targetWidth and targetHeight to tell it
// the size of the thing we're drawing too. We could look 
// up the size of the canvas with gl.canvas.width and
// gl.canvas.height but maybe we want to draw to a framebuffer
// etc.. so might as well pass those in.

// srcX, srcY, srcWidth, srcHeight are in pixels 
// computed from texWidth and texHeight

// dstX, dstY, dstWidth, dstHeight are in pixels
// computed from targetWidth and targetHeight
function drawImage(
    targetWidth, targetHeight,
    tex, texWidth, texHeight,
    srcX, srcY, srcWidth, srcHeight,
    dstX, dstY, dstWidth, dstHeight
) {
  // handle case where only x, y are passed in
  // as in ctx.drawIimage(img, x, y);
  if (srcWidth === undefined) {
    srcWidth  = texWidth;
    srcHeight = texHeight;
  }
  
  // handle case where only x, y, width, height are passed in
  // as in ctx.drawIimage(img, x, y, width, height);
  if (dstX === undefined) {
    dstX = srcX;
    dstY = srcY;
    dstWidth = srcWidth;
    dstHeight = srcHeight;
  }
      
  var mat  = m4.identity();
  var tmat = m4.identity();
  
  var uniforms = {
    matrix: mat,
    textureMatrix: tmat,
    texture: tex,
  };

  // these adjust the unit quad to generate texture coordinates
  // to select part of the src texture

  // NOTE: no check is done that srcX + srcWidth go outside of the
  // texture or are in range in any way. Same for srcY + srcHeight

  m4.translate(tmat, [srcX / texWidth, srcY / texHeight, 0], tmat);
  m4.scale(tmat, [srcWidth / texWidth, srcHeight / texHeight, 1], tmat);

  // these convert from pixels to clip space
  m4.ortho(0, targetWidth, targetHeight, 0, -1, 1, mat);

  // Add in global matrix
  m4.multiply(mat, getCurrentMatrix(), mat);

  // these move and scale the unit quad into the size we want
  // in the target as pixels
  m4.translate(mat, [dstX, dstY, 0], mat);
  m4.scale(mat, [dstWidth, dstHeight, 1], mat);

  gl.useProgram(programInfo.program);
  twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
  twgl.setUniforms(programInfo, uniforms);
  twgl.drawBufferInfo(gl, bufferInfo);
  
}
html, body, canvas {
  margin: 0; width: 100%; height:100%; display: block;
}
<script src="https://twgljs.org/dist/4.x/twgl-full.js"></script>
<script id="vs" type="not-js">
// we will always pass a 0 to 1 unit quad
// and then use matrices to manipulate it
attribute vec4 position;   

uniform mat4 matrix;
uniform mat4 textureMatrix;

varying vec2 texcoord;

void main () {
  gl_Position = matrix * position;
  
  texcoord = (textureMatrix * position).xy;
}
</script>
<script id="fs" type="not-js">
precision mediump float;

varying vec2 texcoord;
uniform sampler2D texture;

void main() {
  gl_FragColor = texture2D(texture, texcoord);
}
</script>
<canvas id="c"></canvas>

and 这是一篇描述其工作原理的文章 https://webglfundamentals.org/webgl/lessons/webgl-2d-drawimage.html

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

WebGL 绘制图像 的相关文章

  • 检查jsonPath中是否有重复的值

    我有一个 jsonPath 如下 book category reference author Nigel Rees title Sayings of the Century price 8 95 category fiction auth
  • Reactjs中的递归函数

    我正在使用递归函数制作动态菜单 并且我已经制作了菜单并且它以正确的顺序显示 没有任何问题 我从以下位置收到菜单数据服务 js文件 您可以在下面的代码沙箱示例中看到整个工作应用程序 https codesandbox io s reactst
  • 在辅助方法中 React i18next useTranslation Hook

    我正在使用 React 和react i18next 我的 index tsx 文件包含一些组件 我可以在那里使用翻译功能 index js import React Suspense from react import ReactDOM
  • 将正则表达式扩展到负数

    我想将以下正则表达式扩展到负数 this value this value replace 0 9 g 我尝试添加减号 执行类似 0 9 g 的操作 但这允许在数字的任何位置输入减号 我只想允许数字开头出现一次减号 随后出现的减号应被忽略
  • PrimeFaces 5.2 及更高版本中图表扩展器属性的替代方案是什么

    我正在使用 primefaces 5 2 最新版本并尝试了折线图 它工作正常 我正在尝试更改折线图轴的颜色 背景 边框等 但扩展器属性在最新的 primefaces 版本中不起作用 我的 XHTML
  • HTML5 下载属性不适用于 Mozilla [重复]

    这个问题在这里已经有答案了 a class download btn href https example com test pdf target blank Download a 我上面有简单的下载链接html5代码 它在 mozilla
  • 上下文保留评估

    我们正在构建一个小型 REPL 来评估 使用eval 用户输入的 JavaScript 表达式 由于整个事情是事件驱动的 因此评估必须在单独的函数中进行 但必须在调用之间保留上下文 即所有声明的变量和函数 我想出了以下解决方案 functi
  • 将另一个类添加到 div

    我有一个函数可以检查表单提交的年龄 然后根据年龄在 div 中返回新内容 现在我只是使用 getElementById 来替换 HTML 内容 但我认为如果我也可以向 div 添加一个类 那对我来说会更好 例如我有 if under cer
  • 在 MVC 5 中,如何在单个 Ajax POST 请求中发送 ViewModel 和文件?

    我有一个 ASP NET MVC 5 应用程序 我正在尝试发送带有模型数据的 POST 请求 并且还包括用户选择的文件 这是我的 ViewModel 为了清晰起见进行了简化 public class Model public string
  • Javascript 递增运算求值顺序

    我知道后缀 前缀递增 递减运算符的作用 而在 javascript 中 这似乎没有什么不同 虽然我可以很容易地猜出这一行的结果 var foo 10 console log foo foo foo foo foo output 10 11
  • 使用嵌套对象进行 Hapi/Joi 验证

    我对我的其中一条路线进行了以下验证 payload keywordGroups Joi array items Joi object keys language Joi string required containsAny Joi arr
  • 响应代码 0 从网站获取 JSON

    我在使用下面的代码时遇到问题 每当我尝试从网站请求 JSON 数据时 我总是会得到响应代码 0 有人知道为什么吗 如果我要访问该网站 我只需输入正确的登录信息即可获取数据
  • 使用 jquery deferreds 处理可变数量的 ajax 请求

    当我有可变数量的 ajax 请求时 如何使用 deferreds 调用它们 我猜 qty of gets 3 function getHTML productID qty of gets var dfd Deferred i 0 c 0 t
  • 删除 highcharts.com 积分链接

    我刚刚购买高图表 http www highcharts com 但制作人员链接仍然出现在我的图表上 这些图表在我的网站上非常突出 并且扭曲了图表视图 我以为我会有一个选项 那么如何删除它呢 您可以自定义制作人员名单 更改 URL 文本 位
  • JavaScript 文件中的代码如何获取文件的 URL?

    我需要将 CSS 样式表动态加载到位于不同的领域 如何获取 JS 文件的完整 URL 以在href样式表的属性 例如 结构如下 http bla com js script js http bla com css style css 我想将
  • 当对象创建或修改 JavaScript 中的键/值时,有没有办法触发回调? [复制]

    这个问题在这里已经有答案了 我试图弄清楚如何在 JavaScript 中创建一个对象 该对象将在创建和更改任意键 值时触发事件 这是一些伪代码 var User function var user function keyAdded tri
  • screen.availHeight 和 window.height() 之间的区别

    我正在我的浏览器 Firefox 上执行以下 Javascript console debug 屏幕高度 屏幕可用高度 输出770 console debug 窗口高度 窗口 height 输出210 我也在使用 jQuery 两者有什么区
  • 在 JavaScript 中使用正则表达式验证信用卡输入

    我一直在努力完成这件事但没有成功 我正在使用正则表达式根据通过单选按钮选择的信用卡类型来验证用户输入的信用卡号 但我一直保持警惕if陈述 看起来所有的if else语句经过测试 There is the HTML code fragment
  • 如何将焦点设置到 django 表单元素的 CharField

    我的登录页面使用 Django 表单 I want to set focus to the first textField username when the page loads 我尝试使用 Jquery 如下 但没有得到结果 forms
  • 流量类型问号?

    对使用 感到困惑在流动中 据我所知 感谢参数之前或之后的流类型问号 https stackoverflow com questions 47314749 flow type question mark before or after par

随机推荐

  • 列出Innodb全文索引的单词

    在 Mysql Innodb 中 我创建了一个全文索引 是否有一个查询可以用来检索全文索引中包含的所有单词的列表 我的想法是使用一个文本字段来保存标签列表的 json 转储 我可以使用全文查询来检索与标签匹配的行 它有效 剩下的问题是检索索
  • ctypes 结构中的默认值

    在 ctypes 结构中 是否可以指定默认值 例如 使用常规 python 函数 您可以执行以下操作 def func a b 2 print a b 这将允许这种行为 func 1 prints 3 func 1 20 prints 21
  • 从传统的基于 XUL 的附加组件中访问附加 SDK?

    我有一个大型且复杂的基于 XUL 的插件 我需要使用插件 SDK 中的一些函数 这可能吗 如果是这样 是否有人有工作示例代码 最好使用 page worker 模块 以下是 devtools 的做法 但某些模块会阻塞 明显的候选者是self
  • 无法访问viewBinding

    我现在正在 Kotlin 中使用 viewBinding here is my build gradle 启用 ViewBinding 并具有自动导入 ViewBinding 依赖项 but Android Studio still sho
  • 如何更好地组织数据库以适应用户状态的变化

    我关注的用户可以是 未确认 或 已确认 后者意味着他们获得完全访问权限 而前者意味着他们正在等待主持人的批准 我不确定如何设计数据库来解释这种结构 我的一个想法是拥有两个不同的表 confirmedUser 和 unconfirmedUse
  • 获取parent.location.url - iframe - 从子级到父级

    我得到了一个在 iframe 中显示的页面 我需要从该页面 子页面 获取带有js的parent location url 两个站点位于不同的域中 我想 警报 父 位置 url 但我收到这个错误 权限被拒绝http 父域 http paren
  • 通过 ASP.NET Identity 和 Autofac OWIN 集成进行授权

    在这个问题的底部添加了更新 我有一个 Web 应用程序 它使用 MVC5 和 WebAPI2 以及 Autofac for DI 该应用程序使用 ASP NET Identity 和 oAuth 不记名令牌 尽管后者可能不是重点 这一切都运
  • C#:存储百分比,50 还是 0.50?

    当在变量中保存百分比值时 会优先将它们保存为整数还是分数 也就是说 变量应该保存 0 到 100 之间的数字还是 0 00 到 1 00 之间的数字 在任何一种情况下 保存值的变量都是十进制类型 我正在交互的数据库恰好将它们存储为 0 到
  • Ionic 项目中的 GSAP

    如何将 GSAP 库导入到 Ionic 项目中 只是使用npm 安装 gsap当我通过导入时不起作用 import TweenMax TimelineMax from gsap 我使用打字稿 谢谢 你不需要打字 我在几个项目中使用过它 所有
  • 克服 Windows 用户对象句柄限制

    我正在寻找在构建重量级 Windows 界面时处理用户对象句柄限制的高级策略 请解释您如何使用 SWT 或直接 Windows GUI API 克服或绕过此问题 我唯一不感兴趣的是优化小部件使用的策略 因为我已经广泛地这样做了 但它并没有解
  • 为什么 RefCell:borrow_mut 在短路布尔 AND (&&) 两侧使用时会导致 BorrowMutError?

    我为 leetcode 编写了这段代码同一棵树问题 https leetcode com problems same tree use std cell RefCell use std rc Rc Definition for a bina
  • 读取文本文件 - fopen 与 ifstream

    谷歌搜索文件输入我发现了两种从文件输入文本的方法 fopen 和 ifstream 下面是两个片段 我有一个文本文件 其中包含一行 其中包含一个我需要读入的整数 我应该使用 fopen 还是 ifstream 片段 1 FOPEN FILE
  • meld - gi.glib.GError:主题中不存在图标“meld-change-apply-right”。安装有什么问题吗?

    我已经成功安装了 meld 3 14 2 和所有依赖包 通过从源代码编译每个包 并且所有包都安装在 NFS 共享上 prefix meld对于融合工具 prefix meld deps对于依赖项 最后 我调用了该工具 我可以看到 GUI 但
  • 隐藏水平滚动条

    我的水平滚动条有问题 我不想让它出现 实际上它只显示在 Chrome 中 而不会显示在 Internet Explorer 中 我能做些什么 我尝试过修改 css 类中的宽度和填充 但这也会改变布局 测试中的内容是动态的 因此它可以垂直溢出
  • 将 Java 类和方法移植到 Android。 (文本布局、字体、Graphics2D 等)

    我一直在 Android 中尝试并尝试通过 Java 应用程序进行移植 以下是我遇到的一些问题 希望得到一些指导 这是一个相当大的问题 而是多个问题 然而 我并不是盲目地询问他们 因为我已经对他们进行了研究 并试图运用我的理解 我花时间提出
  • 在 SQL Server 中将 COALESCE (或类似的东西)与 GROUP BY 一起使用

    我认为我缺少一些关于如何有效使用 GROUP BY 消除冗余记录的基本知识 我不断遇到似乎需要使用 COALESCE 的地方 但据我所知 这不适用于 GROUP BY 示例 我有一个表 其中包含访问 ID 和访问帐单代码的每种组合以及其他有
  • 使用 Cobertura 和 Jacoco 运行代码覆盖率

    我在获取 Maven 插件项目 使用调用程序插件进行集成测试 的 Sonar 中的集成测试和单元测试的代码覆盖率报告时遇到了一些问题 我无法使用默认的 Jacoco 覆盖率工具进行单元测试 因为这些工具使用 Powermock 这会导致使用
  • 如何制作逆序的for循环?

    编者注 这个问题是在 Rust 1 0 发布之前提出的 引入了 范围 运算符 该问题的代码不再代表当前的风格 但下面的一些答案使用了适用于 Rust 1 0 及更高版本的代码 我当时正在玩Rust 示例网站 https rustbyexam
  • 在 DOS/Batch 中,08 小于 1,但 07 大于 1。为什么?

    在 DOS 批处理中 if 08 lss 1 echo true 与 真 相呼应 09也是如此 08和09都小于1 However if 07 lss 1 echo true 不回显任何内容 01至07不小于1 为什么 08年和09年有什么
  • WebGL 绘制图像

    我是 WebGL 新手 之前在 Java 中使用过 OpenGL 我一直在尝试编写一个简单的函数 该函数以特定的大小和旋转在特定位置绘制图像 但在网上搜索了一段时间后 我的代码仍然无法运行 目前 我已经成功绘制了图像 但是该图像距离正确的位