I\'ve been looking at several webgl examples. Consider MDN\'s tutorial. Their vertex shader multiplies the vertex by a perspective matrix and a world position matrix:
I think that JayC and gman got the point.
I would like to try to explain it too.
Fact 1: Javascript on CPU and shader on GPU are two different things and you have to work with them with this on your mind. We have two kinds of shader in WebGL. Vertex shader and fragment shader. Vertex does set of calculations on each vertex and fragment does some set of calculation for every pixel. Shader calculations are usually much more faster then javascript.
Fact 2: Each shader obtains few variables from javascript and it will use them to recalculate vertex/pixel parameters. Number of these variables is limited and each shader loop obtain same variables.
Fact 3: Shader code is much more sensitive then javascript one. Cause javascript is executed once, but shader is always a loop. So if you multiplicate two numbers/matrices 4x4, javascript performance will be almoast same and you will not notice anything. But shader will do it in every loop, so one line can drop performance from ultra high to ultra low. This is what gman says.
So now what is possible to do? (Im not entirely sure that this is possible with webgl shaders, but I think it might be. ) Imagine that you have only few verticies. Like 3, 5 or 20, or even more, it doesnt really matter. And you want to make 100000 matrices multiplications for each vertex. So in fact you can first multiplicate all 100000 things together and then use that result to do just one multiplication with each vertex and you will get a same result as if you multiplicate each vertex 100000 times.
How will you do that. You will pick these 100000 matrices and assume that they are vertices. Then you will write a shader, that will multiplicate it and you will somehow obtain a result. So the multiplication will be pretty fast. And now you will write a shader, that will use a result and will work with final vertices.
But I have to say two things. Im not sure if one shader loop can obtain anything from another loop in webgl. One loop can work only with one vertex and it doesnt see other vertices, but I think you can use attribute variable
to share it. We have only 2 kinds of shaders. Second is, that this task doesnt require expert mind, but genius one.
What about performance? Imagine that you dont want to do 100000 multiplications. You want less, like 2, 3 or 20. Then if you use a shader to do that work, you will have to use pipeline to send data to GPU and then back to CPU, wich can be slower then doing calculations in javascript.
At the end... so even if shader is used for graphic calculations, it is possible to use it in different way. But your approach must be different, conscious and resourceful, which is harder then simple javascript multiplication. Hope it helps everyone.
it depends ....
If you do it in the shader it's done for either every vertex (vertex shader) or every pixel (fragment shader). Even a GPU does not have infinite speed so let's say you are drawing 1million vertices. It's likely 1 set of matrix math calculations in JavaScript vs 1 million matrix calculations in on the GPU, the JavaScript will win.
Of course your milage may very. Every GPU is different. Some GPUs are faster than others. Some drivers do vertex calculations on the CPU. Some CPUs are faster than others.
You can test, unfortunately since you are writing for the web you have no idea what browser the user is running, nor what CPU speed or GPU or driver etc. So, it really depends.
On top of that, passing matrices to the shader is also a non-free operation. In other words it's faster to call gl.uniformMatrix4fv
once than the 4 times you show in your example. If you were drawing 3000 objects whether 12000 calls to gl.uniformMatrix4fv
(4 matrices each) is significantly slower than 3000 calls (1 matrix each) is something you'd have to test.
Further, the browsers teams are working on making math through JavaScript for matrices faster and trying to get it closer to C/C++.
I guess that means there is no right answer except to test and those results will be different for every platform/browser/gpu/drivers/cpu.