Threejs: why is wireframe thickness not adjusting for me? - three.js

I am unable to create thick wireframes. Using the following code:
new THREE.MeshBasicMaterial( {
color: new THREE.Color( 'rgb(100,100,100)' ),
emissive: new THREE.Color( 'rgb(23,23,23)' ),
shading: THREE.FlatShading,
wireframeLinewidth: 10,
wireframe: true
})
I get the following result:
no matter what number I use the lines are always 1px thick. I've noticed that the same is true for threejs api demos page:
is this a known bug? is there any work around?

The maximum required thickness of lines in WebGL1 is 1 so basically your browser or OS or driver has a limit of 1 for line thickness.
In WebGL2 it's even more common for the limit to be 1 because it's 1 in OpenGL 4.0+ Core Profile.
From the OpenGL 4.+ specs, section E.2.1
E.2.1 Deprecated But Still Supported Features
The following features are deprecated, but still present in the core profile. They may be removed from a future version of OpenGL, and are removed in a forward compatible context implementing the core profile.
Wide lines - LineWidth values greater than 1.0 will generate an INVALID_VALUE error.
While WebGL2 is based on OpenGL ES 3.0 on desktops it runs on top of OpenGL 4 or ANGLE both of which have a limit of 1. Since Firefox 51 and Chrome 56 shipped yesterday and both are using ANGLE or OpenGL 4+ on desktops that means the limit is now 1 pretty much everywhere even in WebGL1
The point of all of that is unless you only care about lines of with 1 you shouldn't use GL's line drawing to draw lines (yea, I know, sounds silly).
Instead you need to come up with some other solution.
Some links,
First a library for three.js
https://github.com/spite/THREE.MeshLine
Otherwise some articles about how to create lines
http://labs.hyperandroid.com/efficient-webgl-stroking
https://cesiumjs.org/2013/04/22/Robust-Polyline-Rendering-with-WebGL/
https://mattdesl.svbtle.com/drawing-lines-is-hard

Related

Stroke width, or line material in three-globe

Just trying to up the stroke width a little on the country polygons for three-globe.
There doesn't appear to be a helper function for this material or any settings beyond color.
I had the bright idea of looping through all the children of the globe object, very crude but:
for (let i in Globe.children[0].children[4].children){
const child = Globe.children[0].children[4].children[i];
child.children[1].material.linewidth = 3;
child.children[1].material.color = new THREE.Color('rgba(255,255,255,1)');
}
This appears to have no effect on the line width. It does, however, successfully change the color, so I think I'm close, though I really hope there's a better way than this.
I'm sorry to inform you that the .linewidth property is very poorly supported due to OpenGL limitations. You can see an explanation in the LineBasicMaterial.linewidth documentation
Due to limitations of the OpenGL Core Profile with the WebGL renderer on most platforms linewidth will always be 1 regardless of the set value.
You'll run into this issue if you're using THREE.Line or THREE.LineSegments. However, there is an alternative you could use with THREE.Line2, which circumvents the limitation by drawing lots of instanced gl.TRIANGLES instead of gl.LINE. You can see it in action in this example. In fact, there are 3 demos of fat lines, each one with a slightly different implementation. You would then have to substitute the outlines of the country with your own fat lines.

Three js line thickness

I am using three js and need a way to draw lines that have a thickness greater that 1px. Whenever I use LineBasicMaterial and try to change the lineWidth property, nothing happens. There is already a reason related to Windows Chrome versions so I am asking if there are any good, working alternatives that can help me achieve thick lines.
Here is the material:
const material = new THREE.LineBasicMaterial({
color: "red",
lineWidth: 20
});
https://threejs.org/docs/#api/en/materials/LineBasicMaterial.linewidth
As in the above link said :
.linewidth : Float
Controls line thickness. Default is 1.
Due to limitations of the OpenGL Core Profile with the WebGL renderer on most platforms linewidth will always be 1 regardless of the set value.

WebGL rendering on Firefox - Light effects show darker than in Chrome

I have a scene where one light is present, and diamonds.
Light properties:
Point light, position: 0 0 30, intensity: 1, distance 60, color: White.
The diamonds material is Phong, color:Red, no emissive, specular: White, shininess 10.
On Chrome, the diamons shine as suppose to, but on Firefox the diamonds not shine at all, and looks very dark (like have something black on it).
I have tried to use both Firefox on desktop Windows and Android mobile phone.
I would like to ask what I am missing?
Below are the settings in my code:
// Renderer:
ren=new THREE.WebGLRenderer({ antialias:true,alpha:true });
ren.shadowMap.enabled=true;
elm.appendChild(ren.domElement); // the renderer is added to a DOM element "elm"
// Light
var o=new THREE.PointLight(0xffffff,1,60);
o.position.set(0,0,30);
o.name="sun"; // light will be later added to the scene, and use "update materials" flag to update the materials of the entire scene.
// The diamond's material: (I gave a new parameter "name", for later use. I guess it should not makes trouble to the engine....)
var mt=new THREE.MeshPhongMaterial({ name:"RedDiamond", transparent:true, opacity:0.85, fog:false, color:0xff0020, specular:0xffffff, shininess:10 });
Live example can see here: https://www.crazygao.com/VideoGames/Lamps, since the first level (loading may takes a bit time only for the first time, the opening scene though is yet not complete). The lighting difference issue can be seen even in the progress scene (with the flash one)
My question: What should I do to make the diamonds shine in Firefox, but not make the entire scene too bright in Chrome? (I tried adding Ambient light to the scene, then in Chrome it becomes too bright....)
Is the problem comes from my settings, or it is the nature of Firefox? What are the best steps I can take to solve this issue?
Thanks a lot
My guess is that you're missing that the webgl canvas is composited with the HTML behind it. By default the browser expects the values of the pixels in the canvas to represent premultiplied alpha values. That means there are many possible invalid colors
Example RGBA = 1,1,1,0
That's an invalid color because since alpha = 0 and multiplying by 0 = 0 then R, G, and B also have to be zero
When the values are invalid the results are undefined and so you'll get different results on different browsers
This answers covers some of the solutions.

Using GLSL 3 ES with three.js

Has anyone been successful in using GLSL 3 ES shaders with three.js library?
From what I know it is impossible for latest revision (r68) beacuse one can't even set a directive (which is required, and has to be before anything else in shader code):
#version 300 es
beacause of prefix that is added to each shader by three.js.
Does anyone knows any solution to that problem? Would it be enough to change the three.js code to append the directive on the begining of the threejs shader prefix?
Three.js uses WebGL, which is available in web browsers, not GLES, which is a variant of OpenGL for mobile devices. While it is true that WebGL is itself closely related to GLES2, it is still a different thing. And currently, there only exists WebGL 1.0. Maybe future version will be more related to GLES3, but currently, no WebGL implementation will support ES 3 shaders.
You can use glslVersion property of ShaderMaterial. Don't use #version 300 es directive in shader code.
const material = new three.ShaderMaterial({ uniforms: {},
vertexShader: vscode,
fragmentShader: fscode,
glslVersion: three.GLSL3, });
Three.js is now starting to support WebGL 2.0 on the development branch. You can checkout the development version from Github.
In order to use WebGL 2.0, you can simply create a RawShaderMaterial, with your custom code, and add the #version 300 es directive at the top of your shader source.
EDIT: As of 2020 (Three.js > v113), you can directly use a ShaderMaterial and the framework already adds #version 300 es and performs other kind of conversion automatically when using WebGL2

THREE.JS - Reflections in the windows of a building

I created a building with Blender and imported it in three.js. I managed to give the windows of the building a semi-reflective effect with a cube camera and this line:
geometry.materials[3] = new THREE.MeshLambertMaterial( { color: 0x0000ff, ambient:0x0000aa, envMap: cubeCamera.renderTarget, reflectivity: 0.7, refractionRatio: 0.25 } );
geometry.materials[3] is the Blender material for my windows. Problem is, that this building I created, is a skyscraper and it happens to have plenty of windows. If I do it like above, I get the same reflection in every single window, because there are other materials between the windows and every window-material is isolated from the next window-material by the wall-material. But I would like to have one big reflection over all windows, like if the whole building was only made out of one material. The reflection should only appear in the windows and not on the walls. Windows are all the same material. Is there a way to archieve this behaviour?

Resources