Hi there,
I’m currently porting a geometry line shader with miter/bevels etc to WebGL, which is hard enough as is, but now I’m realizing, that there seems to be no way to change the drawmode to gl.TRIANGLE_STRIP
.
Not changing the drawmode to triangle strips would make it even harder to port the shader and even more inefficient.
Is there really no way to hack into this to allow gl.TRIANGLE_STRIP
as draw mode?
three.js
only supports the default triangle draw mode. The idea is to use BufferGeometryUtils.toTrianglesDrawMode() to convert a strip or fan definition to plain triangles. If you can’t go that route for whatever reasons, you have to modify the engine. However, I recommend to not doing that and rather update other logic of your app so you actually render triangles.
I suppose triangle strip takes somewhat less memory, so it would be nice to support it for the large files. But right, every piece of code that relies on attribute data layout would fall apart.
Thanks for the quick answer!
Well, for me since I’m trying to imitate a geometry shader, its not really about memory, but more about redoing all the calculations even more often …
My vertex shader looks like this:
if (position == 5.0f) {
emit_vertex(p1, +miter_a, v1, vec2(u1, -thickness_aa1), true);
return;
}
if (position == 6.0f) {
emit_vertex(p1, -miter_a, v1, vec2(u1, thickness_aa1), true);
return;
}
if (position == 7.0f) {
emit_vertex(p2, +miter_b, v1, vec2(u2, -thickness_aa2), false);
return;
}
if (position == 8.0f) {
emit_vertex(p2, -miter_b, v1, vec2(u2, thickness_aa2), false);
return;
}
So, no triangle_strip makes this go from bad to worse
I think mugen’s link should work for you with no extra effort
But there are no triangles in the buffer, since i’m generating them in the vertex shader.
I have something like that to emulate the geometry shader:
const geometry = new THREE.InstancedBufferGeometry();
const instance_positions = [0, 1, 2, 3, 4, 5];
geometry.setAttribute(
"position",
new THREE.Float32BufferAttribute(instance_positions, 1)
);
const instanceBuffer = new THREE.InstancedInterleavedBuffer(points, 4, 1); // xy1, xy2
geometry.setAttribute(
"linepoint_prev",
new THREE.InterleavedBufferAttribute(instanceBuffer, 2, 0)
); // xyz1
geometry.setAttribute(
"linepoint_start",
new THREE.InterleavedBufferAttribute(instanceBuffer, 2, 2)
); // xyz1
geometry.setAttribute(
"linepoint_end",
new THREE.InterleavedBufferAttribute(instanceBuffer, 2, 4)
); // xyz1
geometry.setAttribute(
"linepoint_next",
new THREE.InterleavedBufferAttribute(instanceBuffer, 2, 6)
); // xyz2
I think I can change the indices of the instance geometry to change the order from strip to just triangles, but that will make this approach perform even worse (and its already kind of ridiculous to redo most calculations per vertex, which should only be done per line segment)…
Maybe it would be nice if Three.js simply let the draw mode be selected, but make it clear in the docs that some features do not work when the draw mode is not gl.TRIANGLE.
From this comment:
To make it short, it requires much complexity to fully support all draw modes
That’s 100% ok, not all features need to be supported in all draw modes.
At the same time not all features of Three.js are used all the time by everyone, so perhaps if the docs are clear on what works, a user could pick a draw mode with understanding that certain methods are meant to operate on triangles (and not use those methods). Maybe even an error can be thrown when those methods are called if the mode is not compatible.
Use cases
Rendering realtime data in a plotting system with gl.TRIANGLE instead of gl.TRIANGLE_STRIP means 50% more upload to the GPU on each update. Or conversely, if someone were to optimize their plot rendering system from gl.TRIANGLE to gl.TRIANGLE_STRIP, they’d be able to save 33% on upload. That’s a big difference when there is a lot of data involved!
TRIANGLE_STRIP could also be a choice used in a geometry shader, where calculating all the points on the CPU would be far too expensive. As an example, the three-meshline
library could be optimized be converting its vertex calculations into a geometry shader with as few points as possible (TRIANGLE_STRIP).
The VertexShaderArt website is entirely dedicated to geometry shaders, and here are a few examples using TRIANGLE_STRIP:
Can you just build a static geometry.index buffer to emulate a triangle strip?
0,1,2, 1,2,0, 2,3,0, 3,4,0, etc.
imo alternate drawing modes aren’t as relevant in modern times as they used to be… and introduce a lot of complexity, when we’re usually bound more by fillrate + blending.
Strips are funky, and Quads are ill defined.