Adding vertices to a vertex buffer that has already been initialized in WebGL

My journey into learning WebGL has led me to initialize a vertex buffer with data that is designated for gl.STATIC_DRAW. According to the documentation on MDN, gl.STATIC_DRAW is typically used when the vertex data remains constant throughout the application, as explained here:

The contents are intended to be specified once by the application, and used many times as the source for WebGL drawing and image specification commands.

The code snippet I currently have for initializing the vertex buffer is as follows:

const vertices = new Float32Array([
  -1.0, 1.0,   -1.0, -1.0,   1.0, 1.0,   1.0, -1.0
]);
const n = 4;

const vertexBuffer = gl.createBuffer();

gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

const aPosition = gl.getAttribLocation(program, 'aPosition');

gl.vertexAttribPointer(aPosition, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(aPosition);

However, I now have a need to modify the contents of this buffer by adding new vertex coordinates without the need to reinitialize the entire buffer. This led me to consider using gl.DYNAMIC_DRAW for more flexibility, as described in the MDN documentation:

The contents are intended to be respecified repeatedly by the application, and used many times as the source for WebGL drawing and image specification commands.

My dilemma now is how to incorporate this change in usage into my current workflow, specifically in providing new vertices to the existing buffer and triggering a redraw. I haven't come across any examples demonstrating this process.

Your insights and guidance on this matter would be greatly appreciated. Thank you.

Answer №1

There are 2 choices available to you

  1. You can utilize the gl.bufferData function and input your new data

    By doing this, the buffer will be reallocated and your data will be copied in

  2. Alternatively, you can use the gl.bufferSubData function which allows you to copy data to a specific section of the buffer.

    In this scenario, you would first execute gl.bufferData to allocate the buffer, and then use gl.bufferSubData to update the data. If you need to handle varying amounts of data, you can adjust by passing a different count to gl.drawArrays or utilizing different indices with gl.drawElements, etc...

    For example:

    const maxSizeInBytes = 100;
    const buf = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buf);
    // create a buffer with 100 bytes
    gl.bufferData(gl.ARRAY_BUFFER, maxSizeInBytes, gl.DYNAMIC_DRAW);
    

    Later on

    gl.bindBuffer(gl.ARRAY_BUFFER, buf);
    const data = new Float32Array([123, 456, 789]);
    const offsetInBytes = 20;
    // update bytes 20 to 31 of the buffer
    gl.bufferSubData(gl.ARRAY_BUFFER, offsetInBytes, data);
    

It's important to note that the value specified at the end of gl.bufferData is merely a hint. The driver may or may not act upon that hint in a meaningful way.

Furthermore, it is worth mentioning that the most common scenario involves buffer data remaining unchanged. Instead, separate buffers are often created for each object you wish to render, such as "tree", "house", "person", "triangle", "square", "circle", "star", and then the buffers are switched to render different items.

I'm not suggesting that updating buffer contents is discouraged. I simply wanted to convey that in WebGL, many applications do not frequently modify buffer contents. In fact, for most objects rendered, buffer updates are often the exception rather than the rule.

PS: You may find these tutorials to be useful.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to define a variable within a function?

Here's a function designed to verify if the username has admin privileges: module.exports = { checkAdmin: function(username){ var _this = this; var admin = null; sql.execute(sql.format('SELECT * FROM tbl_admins'), (err, result, fields ...

Developing a tool for switching between languages in an internationalization application

I have been exploring the implementation of Lingui(i18n) in apps. All set up, but I'm interested in adding a language switcher to enable users to change between language catalogs on my app. Here's my index.js file: import React, { useEffect } fr ...

What is the best way to transform a JSON object from a remote source into an Array using JavaScript?

Attempting to transform the JSON object retrieved from my Icecast server into an array for easy access to current listener statistics to display in HTML. Below is the JavaScript code being used: const endpoint = 'http://stream.8k.nz:8000/status-json ...

How to ensure an object is consistently rendered above all others using Three.js

Currently working on adding a dynamic command arrow that follows the cursor on the display. However, I have encountered an issue where it gets obscured by other elements on the screen. Is there a method to adjust the z-buffer or implement a workaround to ...

Passing input parameters from a jQuery dialogue box to a handler file (.ashx) in ASP.NET: A step-by-step guide

Hey everyone! I've set up a jQuery dialog box with two input fields as shown below: <div id="dialog" title="Login"> <form action="" method="POST" id="loginForm"> Username: <input type="text" name="username" /><b ...

What sets apart a React component from a function-as-component in React?

React is really confusing to me right now. Take this simple react component for example: export default function Foo(){ return( <div> <div>some text</div> </div> ) } I want to add a child compone ...

Exploring the intricacies of logic through the interactive features of .hover and .click in tandem with Raphael

My goal is to create a hover effect and a click state for a specific area on a map. At present, I want one color to appear when hovering, and another color to display when clicked. Ideally, I'd like the click color to remain even after the user moves ...

How can we customize HTML images without allowing third-party JavaScript to enlarge them?

I am using Blogger to host my website and I have a basic knowledge of HTML and CSS. I want to incorporate a collaborative add-your-link feature using SimplyLinked. However... They provided me with the following HTML: <script type="text/javascript" src ...

Is it possible for the ajax url option to accept an array of URLs rather than just one?

Is there a way to retrieve and store data from multiple JSON URLs in an array? <script type="text/javascript"> urls = ["https://spreadsheets.google.com/feeds/list/1RsiDuydBBHyu4OBjlxq1YH6yT3qcJDMB6-YKU-xxd_k/od6/public/basic?hl=en_US&alt=jso ...

The privateroute is throwing an error because it cannot access the property state since

I stumbled upon a tutorial online detailing how to construct a customized private route, but alas, I am encountering an error. Upon execution, I am faced with the dreaded message: "Cannot read property 'state' of undefined" on line 12. As someon ...

What could be the reason for the absence of 'server' and 'client'?

Trying to retrieve data from db.json but facing some challenges. Below is the content of my db.json file: { "posts": [ { "id": "react-hooks", "title": "React Hooks", "content": "The greatest thing since sliced bread!", "author": "ali" }, ...

block the UI when a certain amount of time has passed

When I click on a button, I implement the following code: $(document).ready(function () { $('.find').click(function () { $.blockUI({ message: '<table><tr><td><img src="images/pleas ...

Is it feasible to maintain a variable as a reference across views while utilizing ng-view?

I am facing a unique challenge: I have a webpage with two tabs that need to utilize ng-view from AngularJS. The twist is that both tabs must share the same variable, similar to referencing a variable in C# using the "ref" keyword. If you want to see an ex ...

Is it possible to verify the versions of node and npm prior to running an npm install command?

To ensure only specific versions of node and npm are used before a user can run the npm install command on my module, I need to set certain criteria. According to NPM documentation, I can use the engine attribute for this purpose: "engines": { "nod ...

What steps should be taken to make mocha utilize the HTTP response?

Every time I make an http call, the function it returns causes my comparison to fail because [Function] is never equal to the value I want. Is there a way to make my assert statement consider the true/false flag within it? # test/helloWorld.js const othe ...

"Resolving the issue of Django request.FILE returning a null value

HTML Template: <form method="post" action="" enctype="multipart/form-data" class="form-group"> {% csrf_token %} <h1 class="m-3 text-center">New Post</h1> <div id="tui-image-e ...

React components can be used to dynamically render and display an array of objects through methods like reduce and

Here's the scenario at hand: (https://codesandbox.io/s/8p21n6p09l) I have an array of objects (referred to as modules) structured like this: const modules = [ { thematicArea: "Topic 1", id: 1, name: "Building assertive attitude", d ...

Transforming an unordered list to function similarly to a select input

I am looking to style a ul list to function as a select form element. I have successfully populated a hidden input using my code. Now, I am trying to make the ul behave like a select input when either the keyboard or mouse is used. Previously, I had some ...

What could be causing my resize event to not trigger?

My goal is for the #sequence div to be full height of the browser window when the window size is greater than 920px in height. In such cases, I also want to trigger a plugin. If the window size is lower than 920px, then the height of the #sequence div shou ...

What is the rationale behind allowing any type in TypeScript, even though it can make it more challenging to detect errors during compile time?

Why is it that all types are allowed in TypeScript? This can lead to potential bugs at runtime, as the use of type "any" makes it harder to detect errors during compilation. Example: const someValue: string = "Some string"; someValue.toExponentia ...