Is there any documentation I can find somewhere which documents the preconditions required for WebGL calls?
I have gotten a fairly strong grasp of the WebGL basics, but now I am creating my own 'framework' and I'm after a deeper understanding.
For example, the enableVertexAttribArray call. Does this call required the current shader to be in 'use'? Where does it store this 'enabled' flag? If I switch shader programs, do I have to re-enable it afterwards when I use it again?
I'd love some kind of diagram explaining where all the 'stateful' information is being stored, and when it will go out of context.
Another example is using gl.bindBuffer, are the buffers for ARRAY_BUFFER and ELEMENT_ARRAY_BUFFER stored in separate locations?
With all this in mind, is it recommended to have a parallel state in JavaScript to avoid running WebGL calls? i.e. storing a 'currentBuffer' object to avoid binding the same buffer over and over if its already bound. I can imagine in the general case, this becomes quite a bit of state duplication, but could be quite good for performance.
Bit of a fundamental question but hard to find info on.
Screenius answer is pretty complete. The terse version is
In WebGL 1.0, uniforms are per program, texture filtering and wrapping is per texture. Everything else is global. That includes all attributes and all texture units.
Pasted from some previous answers that cover this
You can think of attributes and texture units like this
When you call
gl.bindBuffer
you're just setting one of 2 global variables in the gl state.When you call
gl.vertexAttribPointer
it copies current value ofarrayBuffer
to the specified attribute.Textures work similarly
gl.activeTexture
sets which texture unit you're working on.Every texture unit has both a
TEXTURE_2D
and aTEXTURE_CUBEMAP
sogl.bindTexture(b, t)
is effectivelyThe rest is global state like the clear color, viewport, the blend settings, the stencil settings, the enable/disable stuff like
DEPTH_TEST
,SCISSOR_TEST
Just a side note: If you enable the extension OES_vertex_array_object the
vertexArray
in the example above becomes its own object that you can bind withbindVertexArrayOES
.I recently gave a similar answer, but I just said that there's quite a lot and gave a link to the spec, without copy pasting anything. Lesson learned, I can fix that. But just a fair warning, if people call WebGL "stateful" they mean it. But the document, that contains all the errors WebGL can generate under which conditions is called the spec. I'm not copying over all the possible errors, because that would easily double it, if not more.
First, because are you explicitly asked about binding targets, here is how you query all of those, not counting extensions:
Now you don't have to go through this huge list to find those. But if you write a framework, and want to understand the state, you may want to use all the others, too.
getParameter(GLenum pname)
enableVertexAttribArray
andvertexAttribPointer
are setting the state of a vertex attribute array at a specific index, and don't have anything to do with the program. You can also query all this state, by aforementioned index.getVertexAttrib (GLuint index, GLenum pname )
If you now look at the state of the program, there isn't much overlap. One could even go as far as make experiments and see yourself how the states change.
getProgramParameter(WebGLProgram? program, GLenum pname)
Or maybe you want to check how your shader is doing. Still no real overlap in sight.
getShaderParameter(WebGLShader? shader, GLenum pname)
You saw
getVertexAttrib
returns a buffer, so that seems relevant. The buffer itself isn't that much more exciting than say a plain ArrayBuffer. The contents are just not in javacript, but far away in gpu land, doing hard work to support the family at home.getBufferParameter(GLenum target, GLenum pname)
So probably programs and vertex arrays don't have that much in common. Difficult to deduce by guessing, but really simple to find out if you know ( or abstract away ) all those getters.
For completeness, and to help you understand state, I also copy over all the other things.
getFramebufferAttachmentParameter(GLenum target, GLenum attachment, GLenum pname)
getRenderbufferParameter(GLenum target, GLenum pname)
getTexParameter(GLenum target, GLenum pname)
I didn't give up moderating it just yet. So maybe you want to check the value of your uniforms. That's really useful sometimes.
getUniform(WebGLProgram? program, WebGLUniformLocation? location)
Here a few more really useful getters:
getActiveAttrib(WebGLProgram? program, GLuint index)
getActiveUniform(WebGLProgram? program, GLuint index)
And of course the ones everbody loves:
getUniformLocation(WebGLProgram? program, DOMString name)
getAttribLocation(WebGLProgram? program, DOMString name)
getProgramInfoLog(WebGLProgram? program)
getShaderInfoLog(WebGLShader? shader)
getShaderSource(WebGLShader? shader)
getShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype)
getSupportedExtensions()
Oh here that one actually belongs to the vertex attributes, almost forgot. It's separate for important legacy reasons.
getVertexAttribOffset(GLuint index, GLenum pname)
( pname has to be
VERTEX_ATTRIB_ARRAY_POINTER
on that one. )Unless I forgot something, that's basically all of WebGL state. It may seem like a lot, but I personally found all of it to be really helpful to understand how things work. Without those you are basically blindfolded and have to just guess all the time, and follow tutorials telling you the exact order you have to call functions in, which doesn't work well with WebGL - just because there are so many things, but also mistakes you can do.