You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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
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
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
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
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.
The text was updated successfully, but these errors were encountered:
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 callsetBlockUniforms
which copies the values from the JavaScript object into the typedarray that's holding the values for the uniforms. You then callsetUniformBlock
which uploads the typedarray to the corresponding buffer.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
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 outu_lightcolor
from your shader your code breaks. Usingtwgl.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
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
andu_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 JavaScriptAnother 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
Then you could make your shader something like
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
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.
The text was updated successfully, but these errors were encountered: