Draw rounded thick line with WebGL & Three.js - three.js

I just started to fiddle around with WebGL and three.js.
I would really like to create a thick line, which has rounded corners and endings. (see example picture)
Unfortunately I see that firstly the LineBasicMaterial's linecap property does not really work.
Three.js LineBasicMaterial
I started to think about using a tube, but then I think I will still not get a round cap...
Does someone have any ideas how I could create a line in the picture above? It does not necessarily have to made with three.js but WebGL would be a requirement. (I also want to animate this line further on...)
Thanks for any hints.
Cheers

There are a couple ways to draw 3d volumetric lines. The first is to do a vertex expansion in the shader. This is what the links in the comments do. Here is another one in case you need more material: http://codeflow.org/entries/2012/aug/05/webgl-rendering-of-solid-trails/.
Unfortunately it have visual artifacts when the line segment is viewed directly heads on. Check out the demo here: http://codeflow.org/webgl/trails/www/. Spin the scene around and you will notice some line segments facing directly towards the camera will spin rapidly. It looks a lot worse with a less noisy texture btw. If this is fine with you this is probably the preferred option.
The 2nd option is to just dynamically generate a capsule mesh for each line segment. Not much to say about it, beyond that this is a simple, abet somewhat inefficient method.
The 3rd option is to do a limited kind of ray tracing in the shader. Calculate the distance between the line segment and the fragment being shaded and we can use that to determine the appropriate color. Here is a link for that. Geometry shader is not currently supported in the webgl but there is nothing stopping you from generating the bounding line cuboid via javascript. Oh and if you need soft lines you probably need the blend_minmax extension. Probably the hardest method to setup but can be viewed at any angle and very customize-able compared to the other 2 methods.

Related

Threejs - can you use circleBufferGeometry with Points material?

I am setting up a particle system in threejs by adapting the buffer geometry drawcalls example in threejs. I want to create a series of points, but I want them to be round.
The documentation for threejs points says it accepts geometry or buffer geometry, but I also noticed there is a circleBufferGeometry. Can I use this?
Or is there another way to make the points round besides using sprites? I'm not sure, but it seems like loading an image for each particle would cause a lot of unnecessary overhead.
So, in short, is there a more performant or simple way to make a particle system of round particles (spheres or discs) in threejs without sprites?
If you want to draw each "point"/"particle" as a geometric circle, you can use THREE.InstancedBufferGeometry or take a look at this
The geometry of a Points object defines where the points exist in 3D space. It does not define the shape of the points. Points are also drawn as quads, so they're always going to be a square, though they don't have to appear that way.
Your first option is to (as you pointed out) load a texture for each point. I don't really see how this would introduce "a lot" of overhead, because the texture would only be loaded once, and would be applied to all points. But, I'm sure you have your reasons.
Your other option is to create your own shader to draw the point as a circle. This method takes the point as a square, and discards any fragments (multiple fragments make up a pixel) outside the circle.

silhouette rendering with webgl / opengl

I've been trying to render silhouettes on CAD models with webgl. The closest i got to the desired result was with fwidth and a dot between the normal and the eye vector. I found it difficult to control the width though.
I saw another web based viewer and it's capable of doing something like this:
I started digging through the shaders, and the most i could figure out is that this is analytical - an actual line entity is drawn and that the width is achieved by rendering a quad instead of default webgl lines. There is a bunch of logic in the shader and my best guess is that the vertex positions are simply updated on every render.
This is a procedural model, so i guess that for cones and cylinders, two lines can always be allocated, silhouette points computed, and the lines updated.
If that is the case, would it be a good idea to try and do something like this in the shader (maybe it's already happening and i didn't understand it). I can see a cylinder being written to attributes or uniforms and the points computed.
Is there an approach like this already documented somewhere?
edit 8/15/17
I have not found any papers or documented techniques about this. But it got a couple of votes.
Given that i do have information about cylinders and cones, my idea is to sample the normal of that parametric surface from the vertex, push the surface out by some factor that would cover some amount of pixels in screen space, stencil it, and draw a thick line thus clipping it with the actual shape of the surface.
The traditional shader-based method is Gooch shading. The original paper is here:
http://artis.imag.fr/~Cyril.Soler/DEA/NonPhotoRealisticRendering/Papers/p447-gooch.pdf
The old fashing OpenGL technique from Jeff Lander

How can I dull the reflection effect of an environment map (ie. make it blurred / matte)?

I'm currently rendering a skybox to a THREE.CubeCamera target and am then using that target as the environment map on a material. The idea being that I want to have the colour of a cube affected by the colour of the sky around it, though not fully reflecting it (like how a white matte cube would look in the real world).
For example, here is what I have so far applying the environment map to a THREE.LambertMaterial or THREE.PhongMaterial with reflectivity set to 0.7 (same results):
Notice in the first image that the horizon line is clearly visible (this is at sunset when it's most obvious) and that the material is very reflective. The second image shows the same visible horizon line, which moves with the camera as you orbit. The third image shows the box at midday with blue sky above it (notice how the blue is reflected very strongly).
The effect I'm trying to aim for is a duller, perhaps blurred representation of what we can already see working here. I want the sky to affect the cube but I don't want to fully reflect it, instead I want each side of the cube to have a much more subtle effect without a visible horizon line.
I've experimented with the reflection property of the materials without much luck. Yes, it reduces the reflection effect but it also removes most of the colouring taken from the skybox. I've also tried the shininess property of THREE.PhongMaterial but that didn't seem to do much, if anything.
I understand that environment maps are meant to be reflections, however my hope is that there is a way to achieve what I'm after. I want a reflection of the sky, I just need it to be much less precise and instead more blurred / matte.
What could I do to achieve this?
I achieve this writing my own custom shader based on physically based rendering shading model.
I use cook-torrance model that consider roughness of the material for specular contribution. It's not an easy argument that I can talk in this answer, you can find great references here http://graphicrants.blogspot.it/ at the specular BRDF article.
In this question you can find how I achieve the blurry reflection depending on material roughness.
Hope it can help.
I solved this by passing a different set of textures that were blurred to be the cubemap for the object.

how to achieve anti-aliasing in perspective mode?

I want to draw some parallel lines. At first I used gl.LINES but the problem was that the rendered line was one pixel wide at any point on the screen, whether it was very close or very far from the camera.
So instead, I rendered thin rectangles:
As you can see, they now get thinner as they get farther from the camera, but now I get all these ugly aliasing artifacts. Is there a "correct" way to do this in OpenGL/WebGL?
There's a couple of ways to tackle this.
(1) As others have mentioned, just run with super or multisampling.
(2) Use a shader. If you are using Es2/WebGL you are doing that already. But instead of outputting a constant color, write a color plus an alpha that determines how close you are to the line. And then enable blending with that alpha.
One very easy way to do this is to just map a texture as an alpha channel on your rectangle.
Alternatively you can draw 2 quads instead of one and compute the distance in the shader. Then map the distance with a ramp function to alpha.
If you're using GLUT, you can try something like this-
glutInitDisplayMode(GLUT_MULTISAMPLE);// along with all the other flags
If you're not using GLUT, then you can find a very helpful topin on the subject here.
Every platform allows you to do multisampling after getting the OpenGL context.

Outline rendering of transparent cylinders

I am trying to render cylinders for a CAD-like project. As multiple of these will be nested in each other, I am looking to display them similar to this: http://mrwadeturner.pbworks.com/f/1305815353/FC_Cylinder_41702_lg.gif
i.e. I want the outline and the base and bottom circles traced out and the rest should be (semi-)transparent.
Note that this is different from using regular wireframe settings, because that will trace out every face of the sides of the cylinder. The other approach I found - rendering the object twice, once in color and slightly enlarged and once it "regular" version on top - unfortunately won't work either, since multiple cylinders will be nested.
I think this should be possible with custom vertex and fragment shaders, but I am not very proficient in using them. What would be the best way of achieving this effect?
Thanks a lot!
Sound like you just need to apply various textures to the same faces. Next you want to try to create custom texture that is going to be a simple transparent .png image with solid dashed border. Then you'll have to set side:THREE.FrontSide and side:THREE.BackSide to your textures and play around with depthTest.
Another approach is to use lines that you age going to create vertex-by-vertex. See this example for custom line implementation: Hilbert curve and Shapes generation
Hope that helps!

Resources