RE: The adventures of building a web renderer
2019-01-04, 1:23 (This post was last modified: 2021-02-20, 23:06 by Lasse Deleuran.)
2019-01-04, 1:23 (This post was last modified: 2021-02-20, 23:06 by Lasse Deleuran.)
I promised to delete those 7 days of work with conditional lines. I that code I reduced the 1.181.960 conditional lines to [color=#000000]61.401 to be evaluated in each draw call. How about going the other way and evaluate 1.363.920 in each call?[/color]
[color=#000000]That is essentially what happened when I moved this code to:[/color]
[color=#000000]Custom Shaders[/color]
[color=#000000]The idea is to perform the costly calculations on the GPU instead of the CPU. The control points (and opposite line point) are pushed to the GPU and the calculation is performed for each of the two end points of each conditional line (hence the doubling of the calculations).[/color]
[color=#000000]The technical details behind this is to write 'RawMaterials' which use custom WebGL shaders written in the shader language GLSL.[/color]
[color=#000000]Moving the code was not pain free:[/color]
[color=#000000][/color]
[color=#000000]But after fixing the initial rendering problems I was able to get it to work. The main piece of code is in the vertex shader where the alpha component in the color of the conditional line is used to determine if the line should be shown or not:[/color]
[color=#000000][color=#24292e][font=SFMono-Regular, Consolas,][color=#032f62] vColor.a *= sign(dot(d12, d13)*dot(d12, d14));[/font][/color][/color][/color]
[color=#000000]Here 'd12' is the vector difference between points 1 and 2 for the conditional line, 'd13' is between points 1 and 3, and so forth. The dot-operator computes the dot product of two vectors and the sign-operator returns '1', '0' or '-1' depending on the product. [/color]
[color=#000000]The 'fragment shader' can now discard conditional lines that should not be shown:[/color]
[color=#000000][color=#24292e]
[font=SFMono-Regular, Consolas,][color=#032f62] if(vColor.a <= 0.001)
discard;
gl_FragColor = vColor;
[/font][/color][/color][/color]
[color=#000000]The results on the test models are:[/color]
[color=#000000][color=#000000]Psych
- Memory usage: 9.2MB
- Rendering time: 2.519ms
[/color][/color]
[color=#000000][color=#000000]Executor
- Memory usage: 15.2MB
- Rendering time: 47.794ms[/color][/color]
[color=#000000]That is essentially what happened when I moved this code to:[/color]
[color=#000000]Custom Shaders[/color]
[color=#000000]The idea is to perform the costly calculations on the GPU instead of the CPU. The control points (and opposite line point) are pushed to the GPU and the calculation is performed for each of the two end points of each conditional line (hence the doubling of the calculations).[/color]
[color=#000000]The technical details behind this is to write 'RawMaterials' which use custom WebGL shaders written in the shader language GLSL.[/color]
[color=#000000]Moving the code was not pain free:[/color]
[color=#000000][/color]
[color=#000000]But after fixing the initial rendering problems I was able to get it to work. The main piece of code is in the vertex shader where the alpha component in the color of the conditional line is used to determine if the line should be shown or not:[/color]
[color=#000000][color=#24292e][font=SFMono-Regular, Consolas,][color=#032f62] vColor.a *= sign(dot(d12, d13)*dot(d12, d14));[/font][/color][/color][/color]
[color=#000000]Here 'd12' is the vector difference between points 1 and 2 for the conditional line, 'd13' is between points 1 and 3, and so forth. The dot-operator computes the dot product of two vectors and the sign-operator returns '1', '0' or '-1' depending on the product. [/color]
[color=#000000]The 'fragment shader' can now discard conditional lines that should not be shown:[/color]
[color=#000000][color=#24292e]
[font=SFMono-Regular, Consolas,][color=#032f62] if(vColor.a <= 0.001)
discard;
gl_FragColor = vColor;
[/font][/color][/color][/color]
[color=#000000]The results on the test models are:[/color]
[color=#000000][color=#000000]Psych
- Memory usage: 9.2MB
- Rendering time: 2.519ms
[/color][/color]
[color=#000000][color=#000000]Executor
- Memory usage: 15.2MB
- Rendering time: 47.794ms[/color][/color]