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 绘制图像 的相关文章

  • 将 Javascript 对象的属性从 string 更改为 int

    我有一个对象数组 每个对象具有三个属性 年份 总计 人均 例子 0 Object per capita 125 8 total 1007 2 year 2009 这些属性是字符串 我想创建一个循环来遍历数组并将它们转换为 int 我尝试了以
  • 浏览器视口大小(以设备像素为单位)

    Goal 我希望 Flash 能够获得有关浏览器视口宽度和高度 以设备像素为单位 的准确信息初始化 调整大小或浏览器缩放事件时 规格 我需要将 flash 嵌入到在 chrome safari firefox 等中运行的 html 页面中
  • 从函数返回函数的目的是什么?

    阅读一些遗留代码 发现 A prototype setSize function var v1 new Vector2 return function size var halfSize v1 copy size multiplyScala
  • 通过 JavaScript 获取表单名称

    我有一个简单的问题 但我在网上找不到好的解决方案 我有这个 HTML 代码
  • 想要动态处理与分页相关的页码显示:ReactJS

    我有一些分页逻辑工作得很好 唯一的问题是我只能让它显示并固定数量的页面可供选择 现在我已经把它放到了 5 页 但我希望它能够根据总记录动态更改 假设我有 100 条记录 每页限制为 10 条 将有 10 页 现在我只能让它以这种方式显示 第
  • 如何在网站上使用 svg 元素制作块的屏幕截图?

    我在网站上创建了一个构造函数 其本质是将所选元素及其颜色 svg中的元素 添加到访问者选择的背景和背景颜色 png中的背景 中 然后必须单击 保存 结果 按钮并仅执行工作区的屏幕截图 我写了这个脚本 但它需要屏幕截图 但只有背景 并忽略选定
  • JavaScript 验证和 PHP 验证?

    我正在使用 jquery 验证插件来验证空表单 我还应该在 PHP 中检查一下以确保 100 正确吗 或者用 javascript 验证就可以了 谢谢 您应该始终在服务器上进行验证 如果用户以某种方式不使用 Javascript 提交表单
  • 导航栏下拉菜单(折叠)在 Bootstrap 5 中不起作用

    我在尝试使用以下命令创建响应式菜单或下拉按钮时遇到问题Bootstrap 5一切似乎都正常 导航图标和下拉图标出现 但它不起作用 当我单击nav图标或dropdown按钮 无dropdown menu apears 我想特别提到的是 我还包
  • ReactTransitionGroup 不适用于 React-redux 连接组件

    我正在开发一个更大的项目 但我创建了这个简短的示例来说明问题 如果我使用Box组件 它的工作原理 它在控制台中输出componentWillEnter and componentWillLeave当我们点击按钮时 如果我使用BoxConta
  • React Router v4 不渲染组件

    React Router v4 渲染组件存在问题 在应用程序初始加载时 它将呈现与 URL 相对应的正确组件 但是 任何后续的组件Link单击不会呈现所需的组件 图书馆 反应路由器 4 2 2 https reacttraining com
  • 如何使用角度材料在具有可扩展行的表格中创建嵌套垫表

    我有以下数据 id c9d5ab1a subdomain wing domain aircraft part id c9d5ab1a info mimetype application json info dependent parent
  • 如何使用 Javascript 设置查询字符串

    有没有办法使用 javascript 设置查询字符串的值 我的页面有一个过滤器列表 单击该列表时 它将更改右侧的页内结果窗格 我正在尝试更新 url 的查询字符串值 因此如果用户离开页面 然后单击 后退 按钮 他们将返回到最后一个过滤器选择
  • 使用 JavaScript 移动页面上的按钮

    我的按钮可以移动 但奇怪的是 我无法弄清楚偏移是否有问题 我希望我的按钮随着鼠标光标移动 但现在它的移动方式不是我想要的 有时它会消失 另外 创建的新按钮是重叠的 我不知道如何解决这个问题并拥有更好的外观 var coorA var coo
  • 表单发布请求并存储收到的数据

    我有一个非常简单的表单 在提交时发出发布请求
  • 如何使用 JavaScript 或 jQuery 克隆 HTML 元素的样式对象?

    我正在尝试克隆元素的样式对象 这应该允许我在更改后重置所述元素的样式 例如 el style left 50px curr style left 50px Modify the elements style The cloned style
  • 如何从浏览器向服务器发送“页面将关闭”消息?

    我想向每个 html 文档添加一个脚本 JavaScript 该脚本向服务器发送两条消息 页面确实打开了 页面将关闭 此消息包含页面打开的时间 打开消息应在文档加载时 或加载完成时 发送 这是简单的部分 The close message
  • Rails 3.1+ 的 Jasmine 与 Mocha JavaScript 测试 [已关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我对茉莉花有经验并且非常喜欢它 有谁有 Jasmine 和 Mocha 的经验 特别是 Rails 的经验吗 我想知道是否值得转用 我已经在 J
  • 在 iOS 7 Safari 中,如何区分通过边缘滑动与后退/前进按钮的 popstate 事件?

    在 iOS 7 Safari 中 现在有两种后退 前进导航方式 使用底部的传统后退 前进按钮箭头或从屏幕边缘滑动 我正在使用动画在 ajax 应用程序中的页面之间进行转换 但如果用户通过边缘滑动进行导航 我不想触发该转换 因为这本身就是一个
  • 滚动顶部不符合预期

    Note 由于上次忘记奖励而重新开放赏金 A Woff 大师已经给出答案 我想在用户展开某一行时到达该行 这样当最后一个可见行展开时 用户不必向下滚动即可查看内容 I used example tbody on click td green
  • 如何从 json 文件创建模型? (ExtJS)

    这是我想使用 json 文件创建的模型 Ext define Users extend Ext data Model fields name user id type int name user name type string 为了根据服

随机推荐

  • 列出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 我一直在尝试编写一个简单的函数 该函数以特定的大小和旋转在特定位置绘制图像 但在网上搜索了一段时间后 我的代码仍然无法运行 目前 我已经成功绘制了图像 但是该图像距离正确的位