greggman / twgl.js Goto Github PK
View Code? Open in Web Editor NEWA Tiny WebGL helper Library
Home Page: http://twgljs.org
License: MIT License
A Tiny WebGL helper Library
Home Page: http://twgljs.org
License: MIT License
create3DContext
method just get null, and i found that canvas.getContext('webgl', {})
or canvas.getContext('experimental_webgl', {})
both get null in the electron webview.
but it works well in the browers.
my env is
win7 64bit
"electron": "~1.6.2"
navigator.agent: "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36"
Could any help?
Line 179 in 761ec5f
Inside the "createBufferInfoFromArrays", you may get the number of vertex. If the vertex count is greater than 16384. Then, the type of the element index would be 0x1405. So, at this line we can check the type of element before setting the type value, rather than hard coding it to Uint16Array
Hi, I am just trying out Twgl and the experience is amazing ๐. I just wonder if there are more WebGL 2 features coming soon? Like:
It's not possible to update buffer at 0 offset.
But offset = 0
is legal for bufferSubData.
function setAttribInfoBufferFromArray(gl, attribInfo, array, offset) {
array = makeTypedArray(array);
if (offset) { //problem here
gl.bindBuffer(gl.ARRAY_BUFFER, attribInfo.buffer);
gl.bufferSubData(gl.ARRAY_BUFFER, offset, array);
} else {
setBufferFromTypedArray(gl, gl.ARRAY_BUFFER, attribInfo.buffer, array, attribInfo.drawType);
}
}
function setBufferFromTypedArray(gl, type, buffer, array, drawType) {
gl.bindBuffer(type, buffer);
gl.bufferData(type, array, drawType || gl.STATIC_DRAW);
}
If (offset != undefined ) { } ?
Hello, with OffscreenCanvas which is experimental technology permits to use webGL2 in a web Worker. Nevertheless in twgl there is references to window object that doesn't exist in web worker, see here, here and here. Is it possible to change it?
Hi,
FYI, loadCubemapFromUrls method calls a its callback with wrong parameters order.
callback(errors.length ? errors : undefined, imgs, tex);
should be
callback(errors.length ? errors : undefined, tex, imgs);
as defined in CubemapReadyCallback definition.
Same thing with loadSlicesFromUrls method and ThreeDReadyCallback definition.
when i try to use Uint8ClampedArray, twgl throws an "unsupported typed array type" error.
This is related to #14 but a different discussion. The changes made for better browserify/CommonJS support are breaking changes and should bump the major version. Otherwise if I use "twgl": "0.0.x"
or "twgl": "^0.0.27"
or "twgl": "~0.0.27"
and do a npm update
my build breaks. I won't matter much now since it's already on npm, but it's something to consider in the future.
The drawBufferInfo docs say that the fourth argument is "An optional count. Defaults to bufferInfo.numElements". This was true in 3.2.2. When I updated to 3.8.0 my render call was not working anymore. Every time I called drawBufferInfo I got this warning, apparently because it was defaulting to 0:
[.Offscreen-For-WebGL-00000000075EBCE0]RENDER WARNING: Render count or primcount is 0.
When I added an explicit fourth argument with the number of elements in the buffer, I stopped getting that warning message, but the render calls still did not work correctly. (It was as if the render calls were being ignored.)
...I ended up solving the problem by going back to 3.2.2, I can't really say what's wrong except that the behavior changed in a weird way.
hi
isn't there a way like setAttribInfoBufferFromArray
which can change values of indices?
twgl doesn't currently support instancing. Should consider it
The version on the main web page and downloaded as the latest release has a bug where it raises an exception when you try to compile a program without providing the 'opt_attribs'
To reproduce: open the tiny.js example and notice it does not work.
Problem seems to be around twgl.js:1823:
} else if (!Array.isArray(opt_attribs)) { var options = opt_attribs;
opt_errorCallback = options.errorCallback;
opt_attrib = options.attribLocations;
}
Quick fix is to check that opt_attribs is defined before checking if it is an array:
} else if (opt_attribs && !Array.isArray(opt_attribs)) {
var options = opt_attribs;
opt_errorCallback = options.errorCallback;
opt_attribs = options.attribLocations;
}
Also, notice that the last line of the conditional block referenced 'opt_attrib' w/o an 's' which I think is a type-o. I assume it should be 'opt_attribs'
Hello, again a beginner issue about using float frameBuffer to make GPU computation.
My vertex shader:
#version 300 es
in vec2 position;
out vec2 pos;
void main(void) {
pos = position;
gl_Position = vec4(position.xy, 0.0, 1.0);
}
My fragment shader:
#version 300 es
in vec2 pos;
// others uniforms in the future for computation...
out vec3 myOutputColor;
void main() {
// big works here in the future...
myOutputColor = vec3(pos, 3.0);
}
My javascript code:
const width=74;
const height=100;
// init gl
const gl=document.createElement('canvas').getContext('webgl2', { antialias: false });
twgl.addExtensionsToContext(gl);
//init program
const programInfo=twgl.createProgramInfo(gl,vertexCode,fragmentCode);
// define attributes for vertex
const attributes={
position: {numComponents: 2, data:[ 0, 0, width-1,0, width-1, height-1, 0, height-1 ]},
indices:[ 1, 2, 0, 3, 0, 2 ]
};
const attributesInfo=twgl.createBufferInfoFromArrays(gl,attributes);
// define framebuffer
const attachments = [{ internalFormat:gl.RGB32F, minMag: gl.NEAREST, wrap: gl.CLAMP_TO_EDGE }];
const fbi = twgl.createFramebufferInfo(gl, attachments, width,height);
let end;
function render(){
end=new Float32Array(width*height*4);
gl.useProgram(programInfo.program);
twgl.bindFramebufferInfo(gl, fbi);
gl.clear(gl.COLOR_BUFFER_BIT);// GL ERROR :GL_INVALID_FRAMEBUFFER_OPERATION : glClear: framebuffer incomplete
gl.clearColor(0.0, 0.0, 0.0, 1.0);
twgl.setBuffersAndAttributes(gl, programInfo, attributesInfo);
gl.viewport(0, 0, width, height);
twgl.drawBufferInfo(gl, attributesInfo);
gl.readPixels(0, 0, width, height, gl.RGB, gl.FLOAT, end); // GL ERROR :GL_INVALID_FRAMEBUFFER_OPERATION : glDrawElements: framebuffer incomplete
// GL ERROR :GL_INVALID_FRAMEBUFFER_OPERATION : glReadPixels: framebuffer incomplete
console.log(end);
}
I am perplex about this issue. Any help is welcome.
At the moment if I am using non-WebGL2 supported browsers, it dies at
Line 622 in d848b75
It is a pretty minor issue and I can do wrapS
and wrapT
separately for temporary fix but I just want to flag it in case you want to fix it.
setUniforms reassigns a parameter value, which causes chrome to deoptimize the function:
Around line 740:
function setUniforms(setters, values) { // eslint-disable-line
setters = setters.uniformSetters || setters;
A local variable should be used instead to prevent this.
I was using one of previous versions of your library (from 3.8.0) and know when I'm trying to use the latest version I have a problem
the error is
glDrawArrays: attempt to access out of range vertices in attribute 0
I know what is this mean but my code have no problem with previous version
What's the best way for TWGL to support uniform buffer objects?
My usecase does not involve an offset, but reading the code the case offset !== undefined will fail in line 1240: gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
buffer is not defined, should probably be attribInfo.buffer.
I also can't seem to find that method in the API documentation, albeit it has a documentation comment.
It looks like webgl2 is spreading fast, http://webglreport.com/?v=2
Maybe use this as a chance to upgrade to webgl2 and es6 modules and modular shaders (template strings)? I guess that'd bump us to twglThree!
Man what I'd give for a ThreeCore.js. Yes, Three is great in many ways but is pretty hard to adapt to one's own needs. I have zero idea of their architecture such as "Do they to their transforms in the GPU?" or "Can I use ColorMaps so that color is just a small int into a color array uniform?".
I wrote a shader taking three samplers. Two of them would be set once and never change, and the last one would change frequently depending on the texture that was being rendered. I set the first two, static samplers at one location with a programInfo.setUniforms
call and I set the third sampler inside a custom object's render call to be set each time before binding buffers and calling drawArrays. (This was done using an object like {'u_sampler': texture}
.) I found that the second, repeating call that set just one sampler would always override the prior two samplers so that each sampler in the shader referred to the same texture. As a workaround I was able to just update all three samplers in that repeating setUniforms
call, but this doesn't seem like something that should be necessary.
hi
I think that you are separating dist versions in N.x directories for backward compatibility but please add another directory for latest version which the latest version being there always.
thanks
hi
I had saw mdn page of sharedArryaBuffer and it's says it can be use with webgl2 and for reasons I'm using buffers directly with typedArray views. so it's a good feature to support buffers instead of typed arrays .
thank you so much
I added uniform block support but some of the benefits are missing.
As it is it works similar to normal twgl uniforms. You make a JavaScript object with all the values for your uniforms and then instead of calling setUniforms
you call setBlockUniforms
which copies the values from the JavaScript object into the typedarray that's holding the values for the uniforms. You then call setUniformBlock
which uploads the typedarray to the corresponding buffer.
var uniforms = {
u_lightWorldPos: [1, 8, -10],
u_lightColor: [1, 0.8, 0.8, 1],
u_ambient: [0, 0, 0, 1],
u_specular: [1, 1, 1, 1],
u_shininess: 50,
u_specularFactor: 1,
u_diffuse: tex,
};
// copies the uniform values into the typedarray for the uniforms
twgl.setBlockUniforms(someUniformBlockInfo, uniforms);
...
// uploads the typedarray to WebGL and binds it to the correspondingshader's uniforn block
twgl.setUniformBlock(gl, programInfo, someUniformBlockInfo);
The reason there's this 2 step process is because the code becomes brittle without it. If you hardcode uniform names your code will break when debugging and commenting out uniforms etc. In other words you can set the typedarray directly like this
someUniformBlockInfo.uniforms.u_shininess[0] = 50;
someUniformBlockInfo.uniforms.u_lightColor.set([1,0,1,1]);
This will write directly into the typedarray which should be faster than putting your values in JavaScript objects and then calling twgl.setBlockUniforms
. But .... If you then go comment out u_lightcolor
from your shader your code breaks. Using twgl.setBlockUniforms
solves this issue.
Taking it a step further though, the whole point of using Uniform Blocks are (1) they're faster and (2) they can be shared, as in you can use them across programs. Uniform Blocks in WebGL only support the std140 format which means individual uniforms will not get optimized out. If you declare a block
uniform Lights {
mediump vec3 u_lightWorldPos;
mediump vec4 u_lightColor;
} light;
And don't use u_lightColor
it will still exist in the block. So in this case you're safe.
On the other hand if you were to NOT use both u_lightColor
and u_lightWorldPos
then the entire block will not exist and your code trying to set that block will fail. TWGL solves this by making dummy blocks (and printing a warning). It's a trade off. If you aren't checking the console for messages you might mis issues with typos but if you're debugging and commenting out lines in a shader you won't have to restructure your JavaScript
Another solution though would be to be able to give TWGL some kind of block definition separate from the shader. It could create the typedarray with all the accessors which, having no direct connection to the shader, would mean it just always exists, no errors.
But now you have a new problem, you've got to make these uniform definitions separate from the shader itself and keep them in sync with the actual shaders. Now it's turning into a bigger problem. In the interest of D.R.Y. you could have TWGL parse the shader. That's not going to happen as it would take way too much code. You could have TWGL generate the uniform block definition for the shader code. This would be a win because it would mean your blocks would match across shaders and it means D.R.Y. As it is if you have a block in one shader and you're supposed to have a matching block in another but you forget to edit both when adding a field you're screwed. Defining them in one place and including them in your shader would be a win. Something like
const uniformBlockGLSLSnippet = twgl.generateUniformBlockGLSLFromUniformBlockInfo(...)
Then you could make your shader something like
const shaderSource = `#version 300 es
${uniformBlockGLSLSnippet}
...
void main() {
....
But, ... it would also seem to be imposing too much structure. Meaning you'd have to do things the TWGL way. I suppose that's not really true. You wouldn't have to use this stuff. It would just be there if you want to. But no one wants someone else's structure. The structure defining structure would also end up being something that has to be learned
const uniformBlockDefintion = [
{name: "u_lightWorldPos", type: "vec3", precision: "mediump", },
{name: "u_lightColor", type: "vec4", precision: "mediump", },
]);
And adding on structs, arrays, structs of structs, arrays of structs, structs of arrays, arrays of arrays etc. No fun.
I don't really know if there's a solution at the moment or if I should even try to make one. Maybe if you really want to get that optimized you wouldn't be using TWGL in the first place? Or maybe solutions at that level are out of scope. You can still use TWGL even if you decide to implement solutions like these.
I've been trying to use the response from a Fetch load directly in gl.texImage2D to load textures. While converting the response to a Blob works for DOM images, I can't get any form of output to work in gl.texImage2D. I've tried both Blob (attaching to JS Image) and ArrayBuffer. Does anyone have an example of using Fetch output directly in gl.texImage2D or similar methods?
I'm creating several framebuffers with createFramebufferInfo but I'm not doing anything with them yet.
However I noticed I have to explicitly unbind the framebuffer after this call, like this:
this.framebufferInfo = twgl.createFramebufferInfo(gl, [
{
attach: gl.COLOR_ATTACHMENT0,
wrap: gl.REPEAT
}
], this.width, this.height);
twgl.bindFramebufferInfo(this.gl); // <--- unbind framebuffer
If I don't do this I cannot draw on the canvas. (tested with npm module and version 3.7.0).
Is this behaviour intentional?
The cross product implementation makes the assumption that the output vector is not an input vector.
This causes something like v3.cross(a, b, a)
to generate incorrect results.
Despite twgl being updated on npm and saying it's 2.8.2, the version in dist/twgl.js
is actually 1.9.0!
Could this project get published on NPM? If you're not interested in maintaining, I'd be happy to throw it up, but I wanted to see if it's something you want to do.
Would it be within twgl.js's scope to provide some support from returning data from a shader to JavaScript? One could process audio data, or write a shader to generate world transform matrices.
If a library supported this, it could automatically pick the approach to allow for what the local webgl implementation supported (e.g. float pixel values, or transform feedback).
var type = options.type || formatTYpe.type;
https://github.com/greggman/twgl.js/blob/master/src/textures.js#L1247
hi. thanks for es6 module support
I was thinking that if you make a class TWGL and it have it's gl context then we didn't need to pass gl to every functions.
I want to work on it (as a fork) but I thinked it's better to tell you before. then might you like it
We already can create a cube map texture from an array of strings or an array of buffers but I would like to create it from an array of html elements. Would it be possible to add this feature?
Thanks in advance!
The demo for uniform blocks exhibits the issue: http://twgljs.org/examples/uniform-buffer-objects.html
Not sure if this is a bug in Chrome 64 on Windows or in TWGL. The demo seems to work properly in other browsers, even Blink based ones such as Opera.
Hi, I'm really enjoying using Twgl. I'm just missing one thing for now. I'm providing texture mipmaps myself and I would like to call setTextureFromArray with a specified level. Would it be possible to:
I tried it successfully but I'm unsure about any consequences in other use cases.
Thanks in advance!
hi
thanks for adding addExtensionsToContext now we can use instancing but there is a problem
drawObjectList can not draw instance objects I will be happy if you add it as soon as possible and when I want to draw it manually as like the example before or after the drawObjectList called, it make bad thing and it would not draw other objects correctly. please help me fix it
Thanks you
It's unobvious from the twgl docs how to pass in a mat3 uniform. I need to construct it by hand as a Float32Array of length 9, correct? What would be the "ideal" solution?
BufferInfo is kind of a VAO in a sense. Should look into optionally supporting them. Maybe call twgl.useVAOsIfAvailable()
or maybe something more generic like twgl.configure({ useVAOS: true })
I can't require this library in node. This is how to reproduce
npm init
npm install twgl.js --save
node
> var t = require('twgl.js');
Error: Cannot find module 'twgl.js'
at Function.Module._resolveFilename (module.js:336:15)
at Function.Module._load (module.js:278:25)
at Module.require (module.js:365:17)
at require (module.js:384:17)
at repl:1:9
at REPLServer.defaultEval (repl.js:132:27)
at bound (domain.js:254:14)
at REPLServer.runBound [as eval] (domain.js:267:12)
at REPLServer.<anonymous> (repl.js:279:12)
at REPLServer.emit (events.js:107:17)
Hello,
I've been following the project for a while now and I'm loving what I'm seeing!
I've noticed that the examples provided are mostly 3D oriented. From conversations I had with some people, it would be interesting to include some 2D experiments (for eg: 2D Text Visualization, 2D Texture visualization, etc) as in a way to attract more developers.
I'm gonna use TWGL in a current project that is completely 2D oriented (basically transforming my Gibbo2D https://github.com/Whitebeard86/Gibbo2D native application to the web!) so I might be able to provide some examples as well.
Best regards,
John.
The npm twgl.js package that is available at https://www.npmjs.com/package/twgl.js seems to allow only import of the full version of the library (with 3d math and primitives included).
Is it possible to npm install
the minimum version from somewhere?
Hello,
first thanks for your work on twgl. As a beginner in webgl its a great help.
Following your documentation, I try to create a frameBuffer with a certain dimension and I'd like to resizing the created frameBuffer. In chromium, the resizing action generates the following error:
[.Offscreen-For-WebGL-0x23fce9081a00]GL ERROR :GL_INVALID_OPERATION : glTexImage2D: invalid internalformat/format/type combination GL_RGB/GL_RGB/GL_FLOAT
my code is:
const gl=canvas.getContext('webgl2', { antialias: false });
twgl.addExtensionsToContext(gl);
gl.getExtension('EXT_color_buffer_float');
gl.getExtension('OES_texture_float_linear');
gl.getExtension('OES_texture_float');
gl.getExtension('WEBGL_color_buffer_float');
.
.
.
const attachments = [{ format: gl.RGB, type: gl.FLOAT,internalFormat:gl.RGB32F, minMag: gl.NEAREST, wrap: gl.CLAMP_TO_EDGE }];
const fbi = twgl.createFramebufferInfo(gl, attachments, width,height);
twgl.bindFramebufferInfo(gl)
.
.
.
twgl.resizeFramebufferInfo(gl, fbi,attachments, newWidth,newHeight);
I don't understand that createFramebufferInfo
works and with the same attachments attributes, resizeFramebufferInfo
doesn't work....
Hello!
is there are simple way to load external model 3DS OBJ or something else?
thanks
I wrote some typescript definitions for twgl, for a personal project. They don't cover the sub-modules yet, but I would be willing to add them.
However, I don't know how (if at all) to contribute them. I could just create a separate repo and publish them to definitely-typed and "@ types/twgl.js" on npm but I feel like these repos/packages shouldn't be owned by me.
Any suggestions?
I'm torn how best to support Vertex Array Objects in twgl
The issue is, to really use VAOs effectively you have to manually specify attribute locations so that your attributes will match location across programs (positions always attribute 0, normals always attribute 1, texcoords always attribute 2, etc...)
Right now you can specify that by passing stuff to twgl.createProgramInfo
and twgl.createProgram
. I'm wondering if I should let you some how pass in the same data to all the buffer/attribute functions like twgl.createBufferInfoFromArrays
. Or maybe a new twgl.createVAOFromArrays
that requires you to pass in location info.
As it is now you first create a BufferInfo
and then separately you create a VAO passing both a ProgramInfo
and a BufferInfo
to twgl.createVertexArrayInfo
. I did it this way because (1) the locations are specified on the ProgramInfo
and (2) if you don't manually choose locations then you need different VAOs per program.
If I added the new stuff effectively you'd something like
const options = {
attribLocations: {
position: 0,
normal: 1,
texcoord: 2,
binormal: 3,
tangent: 4,
vertexColor: 5,
},
};
Then
const programInfo = twgl.createProgramInfo(gl, [vs, fs], options);
const vaInfo = twgl.createVertexInfoFromArrays(gl, arrays, options);
I could also maybe make some kind of default so you wouldn't have to pass them everywhere like
twgl.setDefaults(options);
Mostly thinking out loud. I've wanted to add this for a while. I'm not 100% sure what kind of extra info is needed though. For example in WebGL2 I need to know if the attribute is a float, int, or unsigned. That info is available on a ProgramInfo
but not currently available anywhere else. I can't look at buffer types since you can pass int and unsigned data to a float attribute. I guess I'd have to extend the attribute location spec so you could add that info
const options = {
attribLocations: {
position: { loc: 0, },
normal: { loc: 1, },
texcoord: { loc: 2, },
binormal: { loc: 3, },
tangent: { loc: 4, },
vertexColor: { loc: 5, type: gl.INTEGER },
},
};
or to the FullArraySpec
. It seems like it belongs on attrib locations though since it's program specific not BufferInfo specific.
I'm trying to use twgl with browserify. There are two small issues.
var twgl = require('twgl.js').twgl;
because for some reason twgl exports an object with a twgl
property instead of exporting itselfmain
in package.json points to the minified file. This makes it impossible to debug locally. I'm not sure though if that was intended?I'm quite confused about m4.multiply().
It looks like the whole m4 is planned with column-major storage in mind (at least it`s what it looks like from reading the code), and this is cool, considering OpenGL defaults to this.
But when it comes to multiplication, the function does something that looks like:
m4.multiply(A,B) = ATBT = (BA)T (?)
or is it just m4.multiply(A,B) = BA
because it multiplies A's columns with B's rows (the opposite would be the usual way, i think).
What triggered this questioning in me was the fact that in the twgl cube example, you built the worldViewProjection matrix by multiplying in reverse order (world * view * projection) compared to most of the literature about modelViewProjection matrices (projection * view * model).
Is this the intention? Am I just messing things up?
Thanks in advance! And great job with the lib (:
Is there an example that implements picking? For example see Draggable CUbes from http://toxicfork.github.io/react-three-renderer-example/
If there is no picking example already, I would like to contribute and create one. My goal is to create a 3d tic tac toe placeholder, so I need to to rotate 3x3x3 cubes and click to select a cube.
AttribInfo incorrectly lists the property "normalized" where it should be "normalize".
This gave me quite a headache :)
So I've got two ideas for managing draw states.
implementation
_The first is similar to how you are managing uniforms:_
Basically it will set the states specified in the first param.
Also if the second optional parameter is true, any unspecified state will be set to their initial states.
mygl.states({
"blend" : true,
"blend_src" : gl.SRC_ALPHA,
"blend_dst" : gl.ONE_MINUS_SRC_ALPHA,
},true);
_The second more similar to gl_
mygl.clearStates(); //set states to be set to initial values
mygl.enable(gl.BLEND);
mygl.blendFunc(gl.SRC_ALPHA,gl.ONE_MINUS_SRC_ALPHA);
mygl.applyStates(); //actually call state functions
_There is also a sync states method so it can be used with other libraries/code that might also be setting states:_
mygl.syncStates();
_edit:_
Just modified how the first example worked.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.