Environment map affects scene lighting after update to r131 - javascript

I have a general scene where I'd like to show different kind of models. Depending on the source of the model sometimes the model contains MeshPhongMaterial, sometimes MeshStandardMaterial, and sometimes both of them.
I also have a specific lighting model with an AmbientLight, and a DirectionalLight that points always to the same direction as the camera, so you will see clearly what you are looking at right now.
To make MeshStandardMaterial look better I've also added an environment map to the scene (not the materials), and I was pretty satisfied with the result.
Here is the result with r130 (Phong material on the left, Standard material on the right):
After I update three.js to r131 the result looks something like this:
I understand that environment maps are auto-converted to PMREM from r131, and this causes the change. I also understand that this is more correct than using non PMREM environment maps, but now it messes up my scene.
On some other topic it was recommended to remove ambient and directional light (because lighting now comes from the environment), but it results in this:
Now the object with standard material looks fine, but the object with phong material is completely black. I've also lost my previous feature that the directional light always points where the camera looks.
By removing ambient light only I get this (still not what I want to achieve):
So basically my question is: Although I know that this is not physically correct, is there a way to apply an environment map that doesn't affect the lighting of the scene, but affects reflections of standard materials?
Here you can find the code of the mentioned scene:
https://github.com/kovacsv/Online3DViewer/blob/dev/sandbox/three_envmap_issue/three_viewer.html
And here you can see it live:
https://raw.githack.com/kovacsv/Online3DViewer/dev/sandbox/three_envmap_issue/envmap_issue.html

So basically my question is: Although I know that this is not physically correct, is there a way to apply an environment map that doesn't affect the lighting of the scene, but affects reflections of standard materials?
No, there isn't. MeshStandardMaterial and MeshPhysicalMaterial require now a more strict PBR workflow. As you pointed out correctly, your previous setup was physically incorrect. This has been fixed and there are no plans right now to allow previous workflows again. Environment maps are considered to be used as IBLs. So conceptually they always affect the lighting no matter how you parameterize the material.
The solution for your use case is to a) use phong materials or b) update the lighting of your scene and accept the new style.

Related

babylon.js meshes get same material

I'm using BabylonJS V3 with Blender 2.79 to create product visualizations. Many times, it is necessary to define more complex shaders in the JS code. I'm using lines like
scene.meshes[1].material.emissiveColor = new BABYLON.Color3(1, 0, 0);
to define the shaders after export. Usually every mesh can get it's own shader this way. Unfortunately in one case, the shader of multiple meshes is overwritten. Did someone have a similar problem?
All meshes are named individually, they all have a basic (individual) shader from blender. They don't share any datablocks, no instancing or duplication was done. I'm thankful for every hint.
Edit
It seems, the error occurs with the new version (3.0), updating to 3.1 fixes the problem, but introduces errors with the arc-rotate camera. As soon as you click on the canvas, to rotate the view, you can't release the mouse anymore. Are the latest stable releases buggy?
Edit 2
After some in depth trouble shooting we came to the conclusion, that the 3.0 and 3.1 versions and/or their exporter plugins are faulty. Even in the simplest testscenes, this error occurs. Alongside other problems, like broken cameras and displaced geometry.
Be aware that by default materials are shared for performance reason. So this is probably not a bug but a feature.
If you want to change the material for a single mesh you will first need to clone it

three.js extend a builtin shader

I want to take an existing working scene setup which has some meshes loaded which render perfectly when setting a MeshLambertMaterial or MeshPhongMaterial onto them. It works with the lights, all the uniforms for the lights are magically being setup under the hood, works great. Shadow mapping works great, too.
Now I want to enhance the shader. I want to add some new stuff in the shader. in my situation this is a set of point lights with hardcoded parameters but you can imagine a practical thing to do would be to open up the ability to configure these dynamically using some uniforms. This is just an intermediate step before re-engineering the render pipeline into performing deferred rendering.
When I go to three.js source and look at renderers/shaders/ShaderLib.js we see that the shader for MeshLambertMaterial is called lambert here and it is constructed mostly out of shader chunks.
What I have done is taken the entire content verbatim and stuck all of this content into my own ShaderMaterial, but my mesh now renders all black.
There is clearly some additional housekeeping that I must do with ShaderMaterial to make it start to behave properly with the lights I have set up through three.js, (so that it is like how the builtin materials behave) but I can't figure out what this is. (I tried RawShaderMaterial but all it did was make a bunch of shader compiler errors about the #if variables not being declared)

Three.js what does computeCentroids do?

I was making my own custom geometry with three.js (using typescript). Something was wrong with it, the object appeared all dark with Lambert material. I checked the three.js source code to see if I forgot to do something when creating the geometry. I saw these two lines appear at the end of the constructor of nearly every geometry class:
this.computeCentroids();
this.computeFaceNormals();
Adding the computeFaceNormals solved my problem. I remember something about normals having to do with lighting (so that makes sense).
But I don't know what the computeCentroids does, and where/why those centroids are needed. Can someone explain? Also do I need to call that function? What can happen if I don't?
computeCentroids calculates the centroid of each triangle in a mesh, not the center of the mesh itself.
Probably the easiest way to see their purpose is to search for .centroid in the three.js source code. AFAICS, they are not used for much apart from lighting, but then only if you're using CanvasRenderer.

three.js outer glow for sphere object?

I'm building some sort of planetary system in three.js and I spent couple of hours looking for a decent solution to get an outer glow on one planet - a sphere object with a texture.
I came across this example http://stemkoski.github.io/Three.js/Selective-Glow.html which kind of does the trick, but the thing is - this form of glow also affects the main 3D object resulting in color change (as seen there).
Another nice glow example can be found here http://bkcore.com/blog/3d/webgl-three-js-animated-selective-glow.html but again it glows the entire region, not only "outer" thing.
I've been reading some discussion thread about "overrideMaterial" property on GitHub but this seems experimental, unused and undocumented... not even sure if this could solve my problem.
Please share your ideas, thanks!
I've worked a bit on separating out the part of the WebGL Globe code (linked to above) that produces the atmospheric effect. A preliminary working version is here:
http://stemkoski.github.io/Three.js/Atmosphere.html
To the best of my understanding, there are a few interesting things going on in the original code to create the atmospheric effect. First, the glowing texture is placed on another sphere -- let's call it the Atmo Sphere :) -- that surrounds the sphere with the image of earth on it. The Atmosphere material is flipped so that the front side does not render, only the back side, thus it does not obscure the earth sphere even though it surrounds it. Second, the gradient lighting effect is achieved by using a fragment shader rather than a texture. However, the atmosphere will change its appearance if you zoom in and out; this was not evident in the WebGL Globe experiment because zooming was disabled.
[updated April 30th]
Next, similar to the source code from
http://stemkoski.github.io/Three.js/Selective-Glow.html
the sphere with the gradient lighting texture (and another black-textured sphere) are placed in a second scene, and then the results from that scene are composed with the original scene using an additive blender. And just so you can experiment with the parameters used to create the glow effect, I have included a couple of sliders so that you can change the values and see the different glow effects that result.
I hope this helps you get started. Good luck!
[updated June 11]
I have a new example which achieves the same effect in a much simpler way, rather than using post-processing and additively blending two scenes, I just changed some of the parameters in the customized material. (It seems obvious in retrospect.) For an updated example, check out:
http://stemkoski.github.io/Three.js/Shader-Halo.html
Still haven't figured out the pan/zoom issues though.
[Updated July 24]
I figured out the pan/zoom issues. It requires using a shader; for details about the complexities, see the related question Three.js - shader code for halo effect, normals need transformation and for the final working example, see:
http://stemkoski.github.io/Three.js/Shader-Glow.html.
I'm pretty happy with the final result, so I will not be updating this answer any more :)
In the example you are referring to, I used a blue glow with additive blending -- if you used a white color instead maybe that would produce the effect you want.

Problems with lights (using three.js)

I have a simple indoor scenario I've exported from blender. It has a room with 3 spheres on the ceiling, and the respective light sources inside them. Each one of the lights work well on their own, but when I insert all of them in the scene, only one of them works! Works with 2, sometimes, but never with the three of them.
Here's my code for the lights:
luz_sala1 = new THREE.PointLight(0xFFFFFF,0.5, 50.0);
luz_sala1.position = new THREE.Vector3(16.14323,2.52331,13.93375);
scene.add(luz_sala1);
luz_sala2 = new THREE.PointLight(0xFFFFFF, 0.5, 50.0);
luz_sala2.position = new THREE.Vector3(27.70114,2.52331,-6.20571);
scene.add(luz_sala2);
luz_sala3 = new THREE.PointLight(0xFFFFFF, 0.5, 50.0);
luz_sala3.position = new THREE.Vector3(21.50580,3.10719,-27.82775);
scene.add(luz_sala3);
If I set the distances to 0, it works well, but I need these lights to influence only the area they are in.
I've also tried with THREE.Spotlight(0xFFFFFF,0.5,50.0,Math.PI, 0) but with the same result.
It looks like the lights negate each other when they share the same distance somehow?
Please help, this is very confusing.
EDIT: Also, I have another section of the room with some spotlight models (I have about 4 of them), but I'm getting shader compiling errors when I add those 4 more spotlights to the scene. After searching for the problem, I saw that I need to set the maxLights property in the renderer. I set it to 10, but the problem still occurs, I can't have more than 4 lights in the scene. Is there anything else I can do?
EDIT 2: Here are some images. For reference, the "luz_sala1" is the one closer to the TV, the "luz_sala2" is the middle one, and the "luz_sala3" is the one more far away.
This one is with the code above (all 3 lights), except with 0.8 intensity.
http://www.mediafire.com/view/?s85qr4rplhort29
And this is with the 2 and 3 turned on (commented the "scene.add(luz_sala1);"):
http://www.mediafire.com/view/?83qbbua9f8ee3b4
So, as you can see, 2 point lights work well together, but with 3 they seem to "add up" to the first?
The maxLight property not having any effect is most likely due to your hardware, drivers or ANGLE (library that translates WebGL to Direct3D) not supporting enough varying vectors in shaders - each light requires one and other things too. This might also be in the background of your general problem.
In order to have more lights there are three options:
Try if it helps if you make your browser prefer native OpenGL over ANGLE (google for instructions). Make sure you have up-to-date OpenGL drivers installed though.
Implement a deferred renderer. This is nowadays very common in the desktop world, but it's tricky if not impossible to implement with good performance in WebGL due to framebuffer limitations.
Implement a light manager that only ever uses some lights, disabling the rest. Simplest, though far from perfect method would be to select the lights closest to the camera.
Also worth mentioning is that currently SpotLights are just PointLights that cast shadow to one direction.

Categories

Resources