我什么时候应该在 WebGL/OpenGL 中启用/禁用顶点位置属性?

2024-01-08

我正在编写一些 WebGL 代码,该代码具有多个按顺序运行的着色器程序。

以前,我使用的是gl.enableVertexAttribArray(...)根据我的 gl 上下文和着色器初始化期间的需要。我假设(也许是错误的)调用此函数是设置特定于由gl.useProgram(...)

现在,我的第一个着色器程序有两个启用的属性数组,第二个着色器程序也启用了一个。当第二个程序运行时,出现错误:

Error: WebGL: drawArrays: no VBO bound to enabled vertex attrib index 1!

因此,这让我认为也许我需要在第一个程序中使用顶点属性 1 后禁用它,但我想验证这就是我应该这样做的方式,并希望得到解释为什么会这样是或不正确。

最好的做法是enableVertexAttribArray(...) and disableVertexAttribArray for every每次使用之前和之后的数组位置?


我从来没有打电话过disableVertexAttribArray在我的一生中,我已经编写了数百个 WebGL 程序。调用它可能有也可能没有任何性能优势,但不调用它不存在兼容性问题。

规范说 https://www.khronos.org/registry/webgl/specs/1.0/#6.5仅当当前程序使用该属性并且访问超出范围或者没有缓冲区绑定到启用的属性时,您才会收到错误。

我们可以测试一下,看看它工作得很好。

var vsThatUses2Attributes = `
  attribute vec4 position;
  attribute vec2 texcoord;
  
  varying vec2 v_texcoord;
  
  void main() {
    v_texcoord = texcoord;
    gl_Position = position;
  }
`;

var vsThatUses1Attribute = `
  attribute vec4 position;
  
  varying vec2 v_texcoord;
  
  void main() {
    v_texcoord = position.xy * 0.5 + 0.5;
    gl_Position = position + vec4(1, 0, 0, 0);
  }
`;

var fs = `
  precision mediump float;
  varying vec2 v_texcoord;
  
  void main () {
    gl_FragColor = vec4(v_texcoord, v_texcoord.x * v_texcoord.y, 1);
  }
`;

var gl = document.querySelector("canvas").getContext("webgl");
document.body.appendChild(gl.canvas);
var programThatUses2Attributes = twgl.createProgramFromSources(gl, [vsThatUses2Attributes, fs]);
var programThatUses1Attribute = twgl.createProgramFromSources(gl, [vsThatUses1Attribute, fs]);

var positionLocation2AttribProg = gl.getAttribLocation(programThatUses2Attributes, "position");
var texcoordLocation2AttribProg = gl.getAttribLocation(programThatUses2Attributes, "texcoord");

var positionLocation1AttribProg = gl.getAttribLocation(programThatUses1Attribute, "position");

var positionBufferFor2AttribPrg = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBufferFor2AttribPrg);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
  -1, -1,
 -.5,  1,
   0, -1,
]), gl.STATIC_DRAW);

var texcoordBufferFor2AttribPrg = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBufferFor2AttribPrg);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
  0, 0,
0.5, 1,
  1, 0,
]), gl.STATIC_DRAW);


var positionBufferFor1AttribPrg = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBufferFor1AttribPrg);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
  -1, -1,
   0, -1,
  -1,  1,
  -1,  1,
   0, -1,
   0,  1,
]), gl.STATIC_DRAW);


// turn on 2 attributes
gl.enableVertexAttribArray(positionLocation2AttribProg);
gl.enableVertexAttribArray(texcoordLocation2AttribProg);

gl.bindBuffer(gl.ARRAY_BUFFER, positionBufferFor2AttribPrg);
gl.vertexAttribPointer(positionLocation2AttribProg, 2, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBufferFor2AttribPrg);
gl.vertexAttribPointer(texcoordLocation2AttribProg, 2, gl.FLOAT, false, 0, 0);

// draw with 2 attributes enabled
gl.useProgram(programThatUses2Attributes);
gl.drawArrays(gl.TRIANGLES, 0, 3);

// setup for second program that uses only 1 attribute
gl.bindBuffer(gl.ARRAY_BUFFER, positionBufferFor1AttribPrg);
gl.vertexAttribPointer(positionLocation1AttribProg, 2, gl.FLOAT, false, 0, 0);

// NOTICE WE HAVE !NOT turned off other attribute
gl.useProgram(programThatUses1Attribute);
gl.drawArrays(gl.TRIANGLES, 0, 6);

log("glError:", gl.getError());

function log() {
  var pre = document.createElement("pre");
  pre.appendChild(document.createTextNode(Array.prototype.join.call(arguments, " ")));
  document.body.appendChild(pre);
}
canvas { border: 1px solid black; }
<script src="https://twgljs.org/dist/twgl.min.js"></script>
<pre>
This example draws a triangle with 3 vertices using 2 attributes.

It then draws a quad using 6 vertices and 1 attribute 
<b>WITHOUT TURNING OFF THE NOW 2nd UNUSED ATTRIBUTE</b>.

That means not only is that attribute left on but it only has 3 vertices even 
though the draw will use 6 vertices. Because that attribute is not 'comsumed' by 
the current program it's ok according to the spec.
</pre>
<canvas width="150" height="30"></canvas>

因此,您的错误可能是其他原因。

请注意,删除缓冲区会将其与属性解除绑定,此时它将成为没有缓冲区的启用属性,并会导致错误,除非禁用它。

属性状态与您发现的程序状态是分开的。

你的错误的意思正是它所说的。您尝试绘制,该程序需要属性#1 上的数据。您在某个时候启用了它gl.enableVertexAttribArray但你没有给它任何数据gl.vertexAttribPointer。所以你有一个错误。

注意gl.vertexAttribPointer绑定当前绑定的缓冲区gl.ARRAY_BUFFER到指定的属性。

您可能会发现这个答案很有用

https://stackoverflow.com/a/27164577/128511 https://stackoverflow.com/a/27164577/128511

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

我什么时候应该在 WebGL/OpenGL 中启用/禁用顶点位置属性? 的相关文章

  • 调用“DOMNodeInserted”事件时添加元素

    我想在每个 喜欢 按钮 chrome 扩展 之后添加一个元素 由于帖子被添加到新闻提要而不刷新页面 我必须添加一个事件侦听器 DOMNodeInserted 但是当我尝试把after 里面的功能 它不起作用 Code contentArea
  • ReferenceError:找不到变量:需要

    我在加载时遇到问题node modules到我的网页之一 我已经安装了 npm node js 并且我想使用require 函数在我的网站上初始化 Firebase 我不知道为什么 但它抛出引用错误 ReferenceError 找不到变量
  • HTMLImageElement 作为 React Child 无效

    我正在尝试异步加载图像 并且仅在加载图像后才将其显示在 React 应用程序中 componentDidMount const img new Image img onload gt this setState originalImage
  • 如何使用键盘和鼠标控制相机 - Three.js

    我在 WEB GL 中有一个带有 Three js 的 3D 环境 并且我曾经使用 Orbitcontrols js http codepen io nireno pen cAoGI http codepen io nireno pen c
  • 为什么 jQuery 点击事件会多次触发

    我这里有这个示例代码http jsfiddle net DBBUL 10 http jsfiddle net DBBUL 10 document ready function creategene click function confir
  • 在浏览器中语音聊天? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我们正在寻求建立一个小组 voice 使用服务器上的node js 在浏览器中聊天 这可能吗 如果您希望您的解决方案是基于服务器端和客
  • 将 jquery-mobile 与 Webpack 结合使用

    我正在尝试使用 webpack 加载 jquery mobile 但到目前为止还没有运气 我知道 jquery mobile 依赖于 jquery ui 而 jquery ui 又依赖于 jquery 如何在 Webpack 中设置这样的场
  • 未捕获的引用错误:myFunction 未定义[重复]

    这个问题在这里已经有答案了 这到底是怎么回事 http jsfiddle net sVT54 http jsfiddle net sVT54
  • 如何改变HTML5视频的播放速度?

    如何更改 HTML5 中的视频播放速度 我查过视频标签的属性 https www w3schools com html html5 video asp在 w3school 但无法做到这一点 根据这个网站 http www chipwreck
  • Aptana Studio 3 上的预览选项卡在哪里?

    我在 Windows PC 上使用 Aptana Studio 2 并有一个选项卡用于在 IE 上预览页面 另一个选项卡用于在 Firefox 上预览 但我切换到了 Aptana 3 我不知道是没有预览还是我没有找到它 是的 我在 stac
  • jQuery 选择器:为什么 $("#id").find("p") 比 $("#id p") 更快

    该页面的作者 http 24ways org 2011 your jquery now with less suck http 24ways org 2011 your jquery now with less suck断言 jQuery
  • 如何清除WebGL中的矩形区域?

    WebGL 有一个clear清除整个表面的方法 清除表面的特定矩形的最佳方法是什么 例如 我想将一个从 50 50 开始的 100x100 像素框设置为全零 ARGB 0 0 0 0 我现在能想到的就是用一个写入零的片段着色器绘制一个四边形
  • 选中复选框时提交表单

    有没有办法在选中复选框时提交表单
  • 如何将 Browserify 与外部依赖项一起使用?

    我正在尝试慢慢地将 Browserify 引入我的网站 但我不想重写所有 js 也不希望 jquery 和其他库的重复实例与我的 Browserify 版本捆绑在一起 如果我构建将 jquery 列为外部依赖项的模块 那么如何将其指向我的全
  • 如何在 e2e AngularJS 测试中进行文件上传?

    在我的一种观点中 我有一个文件上传控件 它支持通过拖放或单击按钮后打开的标准文件对话框上传文件 How to do this in my e2e tests1 1 Just one of the two options will be en
  • WebRTC:通道、轨道和流与 RTP SSRC 和 RTP 会话之间的关系

    来自 Mozilla 网站 https developer mozilla org en US docs Web API Media Streams API https developer mozilla org en US docs We
  • ng-model 和值组合不适用于输入文本框

    我有两个输入文本框 我需要组合在两个文本框中输入的值并将其显示在第三个文本框中 如果我只使用value在第三个文本框中 Box 1
  • 如何获取使用 .map 渲染的第一个元素的 ref?

    我需要在几行中显示视频 卡片 的缩略图 并重点关注第一个缩略图 我使用嵌套地图进行了显示 该代码基本上迭代视频数组并返回多行视频 我们如何关注第一个渲染的元素 我认为我们需要获得第一个要聚焦的元素的引用 但是我们如何在这里设置 ref 并在
  • React Native - 跨屏幕传递数据

    我遇到了一些麻烦react native应用程序 我不知道如何跨屏幕传递数据 我意识到还有其他类似的问题在 SO 上得到了回答 但是这些解决方案对我来说不起作用 我正在使用StackNavigator 这是我的设置App js file e
  • Django 与谷歌图表

    我试图让谷歌图表显示在我的页面上 但我不知道如何将值从 django 视图传递到 javascript 以便我可以绘制图表 姜戈代码 array Year Sales Expenses 2004 1000 400 2005 1170 460

随机推荐

  • 在 Perl 中,如何按值的频率排序?

    我正在尝试创建一个程序来计算数据文件列中出现的不同值 因此 如果一列的可能值为 A B C 则输出类似于 A 456 B 234 C 344 通过执行以下操作 我可以轻松获得 A B 和 C 的运行计数 my count for my f
  • 使用 Mono.Cecil 替换对类型/命名空间的引用

    背景 不必要的 令人困惑的 仅供好奇的人使用 我正在使用 Unity3D for Mobile 的免费版本 它不允许我使用System Net Sockets移动设备上的命名空间 问题是我正在使用编译的 dll引用的库 即 IKVM Sys
  • Haskell 脸书示例

    我被 haskell 类型困住了 LANGUAGE OverloadedStrings module Main main where import qualified Facebook as FB import Network HTTP C
  • 如何使用 powershell 在 wsl 上运行 bash 脚本?

    在 Windows 上的当前目录中 我有以下脚本文件 simple script sh bin bash echo hi from simple script 我希望通过 powershell 命令行在 wsl 上运行此脚本 使用wsl命令
  • 自动将 Sybase .ADT 文件转换为 SQL

    我正在处理我获得的一些数据 这些数据是通过使用嵌入式 Advantage 数据库服务器的程序读取的 该程序不是我编写的 并且不具备我需要的所有功能 我想将这些数据转换为不同的格式 以便我可以更自由地使用它 例如 MySQL 我知道Sybas
  • 防止将重复的项目添加到列表框中

    我有这段代码用于添加选定的项目ListBox到另一个 如何防止用户重复添加某个项目 我想要ListBox他们正在添加lstBoxToUserProjects仅包含不同的项目 没有重复的条目 protected void btnAddSele
  • AsyncTask 错误中的 Android JSON

    我正在尝试使用 asynctask 从 google 获取 JSON 数据 但我收到很多错误 我不知道为什么 我是 Android 开发的新手 我对它很感兴趣 然后又退出了 P 然后单击执行异步任务的按钮 new usdjson execu
  • 使用 Yii 自动存储日期时间

    我开始使用 Yii 学习 php 我有一个很大的问题 也许你可以帮助我 我正在使用表单来创建用户 我想将表单中引入的用户数据存储到数据库 MySQL 中 但我还必须将日期和时间存储在数据库的日期时间字段中 我看到一些扩展如 CJUIDATE
  • TYPO3:从 Extbase 中的文件引用中获取路径

    我使用 Fluid 和 Extbase TYPO3 6 1 创建了一个自定义内容元素 您可以在其中定义图片 在图片设置中 我可以设置一个img链接 它的目标是一个文件 在我的控制器中我可以访问这些数据 this gt configurati
  • webkit 中的 CSS3 动画暂停/取消暂停跳过和跳跃

    我已经实现了动画暂停 如下所述 如何使用 JavaScript 暂停和恢复 CSS3 动画 https stackoverflow com questions 5804444 how to pause and resume css3 ani
  • XAML:DataTemplate 中的自定义绑定用于 GridViewColumn CellTemplate

    我希望在整个 GridView 中重用资源中的以下 DataTemplate
  • 如何实现hashCode和equals方法

    我应该如何实施hashCode and equals 对于 Java 中的以下类 class Emp int empid unique across all the departments String name String dept n
  • 高分辨率的响应式字体大小在 MUI 5 中不起作用

    我在用材质 UI v5 https mui com 在我的 React 应用程序中 并使用响应式字体大小 https mui com customization theming responsivefontsizes theme optio
  • Android:findViewById() 方法返回我们不需要转换的值

    因为我厌倦了为每个人编写一个强制转换运算符Activity findViewById 返回原始数据View 我终于尝试了互联网建议的一种方法 http biginteger blogspot jp 2011 04 better findvi
  • C#:Func<> 而不是方法? [复制]

    这个问题在这里已经有答案了 这是一个让大家好奇的问题 使用 Func 而不是方法有什么坏处 缺点吗 简单的例子 private static Func
  • Glide 不接受 GifDrawable 作为目标参数

    我试图用 glide 找出 gif 的结尾 这是我在网上找到的代码 Glide with thisActivity asGif load R raw logo gif motion low listener object RequestLi
  • 在 C# 中搜索子目录

    我有一个文件名列表 我想搜索一个目录及其所有子目录 这些目录每个包含大约 200 000 个文件 我的代码找到该文件 但每个文件大约需要 20 分钟 有人可以建议更好的方法吗 代码片段 String file names File Read
  • 在 Rails 中通过 JS 设计注册#update

    我正在尝试通过 Devise 使用 AJAX 更新用户模型 并让 Devise 使用正确的 javascript 文件进行响应 我想将表单远程提交到 Registrations update 操作 但这不适用于 Devise 的默认响应 它
  • 在 PHP 中初始化(空)数组的最佳方法

    在某些其他语言 例如 AS3 中 已经注意到 如果这样做 初始化新数组会更快var foo 而不是var foo new Array 出于对象创建和实例化的原因 我想知道 PHP 中是否有等价的东西 class Foo private ar
  • 我什么时候应该在 WebGL/OpenGL 中启用/禁用顶点位置属性?

    我正在编写一些 WebGL 代码 该代码具有多个按顺序运行的着色器程序 以前 我使用的是gl enableVertexAttribArray 根据我的 gl 上下文和着色器初始化期间的需要 我假设 也许是错误的 调用此函数是设置特定于由gl