Comments (6)
The reason it probably failed before is with the gl.activeTexture
at the bottom the code was doing this
- first iteration
- bind texture to texture unit 0 (because active texture unit defaults to 0)
- ...set params...upload data..
- bind texture to texture unit 0
- second iteration
- bind texture to texture unit 0 (it has not been changed since the last iteration)
- ...set params...upload data..
- bind texture to texture unit 1
At this point the second texture is bound to both units 0 and 1
unit 0 = 2nd texture
unit 1 = 2nd texture
If we had a 3rd iteration
- third iteration
- bind texture to texture unit 1 (it has not been changed since the last iteration)
- ...set params...upload data..
- bind texture to texture unit 2
now the state is this
unit 0 = 2nd texture
unit 1 = 3nd texture
unit 2 = 3rd texture
Once you moved the gl.activeTexture
to the top that fixed things so after 3 iterations you'd have this
unit 0 = 1st texture
unit 1 = 2nd texture
unit 2 = 3rd texture
Comment on the code:
You don't need to make strings for GL constants. There's nothing special about the constants in WebGL. These are all the same
gl.activeTexture(gl[`TEXTURE${index}`]);
gl.activeTexture(gl.TEXUTRE0 + index);
gl.activeTexture(33984 + index);
Of course maybe you were making a string because you wanted to print it somewhere else. That's fine. Just pointing out you don't need to use the actual properties on the WebGLRenderingContext (gl
). They're just numbers, they don't change.
As for deleting you should delete WebGL objects yourself. Yes, they will eventually get garbage collected but the problem is JavaScript doesn't know anything about the memory used for textures (or other WebGL objects). As far as it's concerned a texture is just some tiny tracking object to some opaque thing. JavaScript doesn't know how much VRAM there is, nor does it know that freeing these opaque texture tracking objects will free up VRAM when VRAM is full.
So, free (delete) webgl objects when you no longer need them.
I'd say the majority of WebGL apps (which are mostly visualizations like the ones here) never free anything because they just load the stuff they need and use all of it until the page is closed. For apps that do more though, like a photo editor, they would need to do more and delete things themselves.
from webgl-fundamentals.
I'm sorry you found it confusing. There's no need to specify an active texture unit at the beginning. Creating textures and putting data in them and setting their parameters is entirely unrelated to using them at render time.
There are only 8 to 32 texture units (depending on your GPU). They are how you tell a shader which textures to use. Separately you can have 1000s of textures, way more than active texture units.
Before rendering something (before calling gl.drawArrays or gl.drawElements) you need set up the texture units to point to the textures used used for that draw call.
from webgl-fundamentals.
One more example based on my comment above. Imagine we have code to make 8 textures
function makeTexture(gl, color) {
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXUTRE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(color));
return tex;
}
const textures = {
red: makeTexture(gl, [255, 0, 0, 255]),
yellow: makeTexture(gl, [255, 255, 0, 255]),
green: makeTexture(gl, [ 0, 255, 0, 255]),
cyan: makeTexture(gl, [ 0, 255, 255, 255]),
blue: makeTexture(gl, [ 0, 0, 255, 255]),
magenta: makeTexture(gl, [255, 0, 255, 255]),
black: makeTexture(gl, [ 0, 0, 0, 255]),
white: makeTexture(gl, [255, 255, 255, 255]),
};
Then at render time we can any texture on any texture unit. We just need to tell our shader which texture units we bound our textures to. Just to be random let's use texture units 3 and 7
// --- [draw something]---
gl.activeTexture(gl.TEXTURE3);
gl.bindTexture(gl.TEXTURE_2D, textures.blue); // put blue on unit 3
gl.activeTexture(gl.TEXTURE7);
gl.bindTexture(gl.TEXTURE_2D, textures.yellow); // put yellow on unit 7
gl.uniform1i(someUniformSamplerLocation, 3); // tell the shader to use unit 3 for this uniform sampler
gl.uniform1i(someOtherUniformSamplerLocation, 7); // tell the shader to use unit 7 for this uniform sampler
gl.drawArrays(....);
// --- [draw something else]---
gl.activeTexture(gl.TEXTURE3);
gl.bindTexture(gl.TEXTURE_2D, textures.cyan); // put cyan on unit 3
gl.activeTexture(gl.TEXTURE7);
gl.bindTexture(gl.TEXTURE_2D, textures.magenta); // put magenta on unit 7
gl.uniform1i(someUniformSamplerLocation, 3); // tell the shader to use unit 3 for this uniform sampler
gl.uniform1i(someOtherUniformSamplerLocation, 7); // tell the shader to use unit 7 for this uniform sampler
gl.drawArrays(....);
// Use different texture units just for the heck of it
gl.activeTexture(gl.TEXTURE6);
gl.bindTexture(gl.TEXTURE_2D, textures.white); // put white on unit 6
gl.activeTexture(gl.TEXTURE2);
gl.bindTexture(gl.TEXTURE_2D, textures.red); // put red on unit 2
gl.uniform1i(someUniformSamplerLocation, 6); // tell the shader to use unit 6 for this uniform sampler
gl.uniform1i(someOtherUniformSamplerLocation, 2); // tell the shader to use unit 2 for this uniform sampler
gl.drawArrays(....);
you might find this helpful
from webgl-fundamentals.
Well, this is something I was pointing out: I might be wrong but following the javascript implementation
example, calling texImage2D
will upload the data to TEXTURE0
so the for loop will populate with data only the first texture unit.
I do understand that bindTexture
should specify to which texture am I uploading the data, yet until I started specifying the actual texture unit before calling texImage2D
it did not work.
The javascript implementation
uses
var activeTexture = function(unit) {
function to set up active unit and
var texImage2D = function(target, ... args ...) {
uses the location of activeTexture
as where to load the data
So either of these examples (the code you showed above and the demo javascript OpenGL api implementation) in the tutorial should be wrong...
PS: you don't need to provide any example codes - I am already kind of advanced OpenGL user - I only struggle with the basics API such as order of calls and arguments, since we usually use frameworks in C++ that automate this painful coding, yet one project in WebGL has none, so I had to re-learn this :) thanks anyway
from webgl-fundamentals.
yet until I started specifying the actual texture unit before calling texImage2D it did not work.
If you post your code we can look over it and figure out what the issue is
So either of these examples (the code you showed above and the demo javascript OpenGL api implementation) in the tutorial should be wrong...
The samples are not wrong
"Texture Units" are not "Textures". Texture Units are just a global array of references to textures. When setting up a texture which texture unit is active is mostly irrelevant. What's relevant is what they are when you call gl.drawArrays
or gl.drawElements
In the code, after the first iteration of the loading loop
// create 2 textures
var textures = [];
for (var ii = 0; ii < 2; ++ii) {
var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
// Set the parameters so we can render any size image.
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
// Upload the image into the texture.
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, images[ii]);
// add the texture to the array of textures.
textures.push(texture);
}
the state will be like this
After the second iteration of the loading loop the state will be like this
After the setup in the rendering part of the code,
// set which texture units to render with.
gl.uniform1i(u_image0Location, 0); // texture unit 0
gl.uniform1i(u_image1Location, 1); // texture unit 1
// Set each texture unit to use a particular texture.
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, textures[0]);
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, textures[1]);
just before calling gl.drawArrays
the state will be like this
I am already kind of advanced OpenGL user
Me too 😉 I wrote the WebGL implementation in both Chrome and WebKit, I wrote the GPU infrastructure in Chrome including an entire OpenGL ES driver, and I wrote the majority of the WebGL1 Conformance Tests 😉
from webgl-fundamentals.
Ah, I see. I did not read the whole thing and it re-uses the spot for different pointers.
let _this = this,
index = 0;
const NUM_IMAGES = Math.round(image.height / tileBounds.height);
//images are sent below each other, it can be passed at once into IMAGE_ARRAY, this is inside WebGL 1.0 strategy fallback
this.canvas.width = image.width;
this.canvas.height = image.height;
this.canvasReader.drawImage(image, 0, 0);
//the logic of not running out of tex units is somewhere else
for (let key in visualisation.shaders) {
let layer = visualisation.shaders[key];
this._units.push(gl.createTexture());
let bindConst = `TEXTURE${index}`;
gl.activeTexture(gl[bindConst]); //started working only after calling it now
let location = gl.getUniformLocation(program, `data_${layer.order}`);
gl.uniform1i(location, index);
gl.bindTexture(gl.TEXTURE_2D, this._units[index]);
//some params
gl.texParameteri(...);
let read = this.canvasReader.getImageData(0, layer.order*tileBounds.height, tileBounds.width, tileBounds.height);
let pixels = new Uint8Array(read.data.buffer);
gl.texImage2D(gl.TEXTURE_2D,
0,
gl.RGBA,
tileBounds.width,
tileBounds.height,
0,
gl.RGBA,
gl.UNSIGNED_BYTE,
pixels);
//previously, the code had been here (followng the example):
// gl.activeTexture(gl[bindConst]);
// gl.bindTexture(gl.TEXTURE_2D, this._units[index]);
index++;
}
So I do get what changed - I am reusing multiple spaces in the pointer array to load my data into textures and since I immediately use it actually saves me some API calls. However, why it was not working before leaves me clueless.
Offtopic: I was also wondering what about memory management: when do you DELETE textures? Almost nowhere is an example of how (or rather: when) to clean up after yourself. Is it ok to leave it just like that and all will be freed when the GC collects the canvas?
Thank you.
from webgl-fundamentals.
Related Issues (20)
- Duplicate gl.bindBuffer in webgl-fundamentals.html? HOT 1
- Suggestion: How about to use unit square instead of unit quad? HOT 4
- Is the example lost? HOT 3
- Is it modulo or module? HOT 1
- Explanation error HOT 1
- Skinning inverse world matrix HOT 1
- possible bug in m3.js HOT 1
- another bug in m3.js HOT 3
- error in textures example code HOT 2
- [SUGGESTION] Point Sprites HOT 4
- data-textures: Mention (data in texture)=(data supplied)/255?
- webgl-state-diagram use-2-programs does not work HOT 6
- Broken links HOT 1
- webgl state diagram : draw on cube
- webgl-state-diagram: extraneous column heading in vertex array HOT 2
- Broken link in Load Obj HOT 1
- webgl-how-it-works.html: some poor rounding, one wrong number
- webgl-image-processing: images don't actually have to be same-origin
- Camera tutorial requirements
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from webgl-fundamentals.