AmbientLight display differences - three.js

I tried to illuminate the model with AmbientLight of three.js. I used the same light source in the test environment and the production environment, but found that the color rendering was different. The whole process I sorted out couldn't find the difference.
let ambColor = new THREE.Color('rgb(255, 255, 255)');
this.ambientLight = new THREE.AmbientLight(ambColor)
this.scene.add(this.ambientLight)
Test environment:
Production environment:
The test environment was obviously brighter, and I also tried turning off the AmbientLight to make sure the lights did work.
example file

Check where you call your renderer, you might be using one of these:
//Physically Correct Lights
renderer.physicallyCorrectLights = true
//In your update function, maybe removed the env map from the scene, but forgot about removing it from your update function too.
if(child instanceof THREE.Mesh && child.material instanceof THREE.MeshStandardMaterial){
child.material.envMap = environmentMap
}
//Output encoding (by default is LinearEncoding)
renderer.outputEncoding = THREE.LinearEncoding
//Tone mapping (by default is NoToneMapping)
renderer.toneMapping = THREE.NoToneMapping
If not, try removing everything in both environements but the models and lights. Check if the three.js version is the same.
PD: Try using more light sources and shadows, you will get a better result.
Ambient light:
Ambient light + Point light:
This was free content available on Bruno Simon's course

Related

Using CubeRefractionMapping with THREE.CubeCamera renders upside down

If I set the renderTarget mapping for my cube camera to THREE.CubeRefractionMapping, it renders upside down.
_myCubeCamera.renderTarget.mapping = THREE.CubeRefractionMapping;
It seems related to the issue discussed in this post where the default orientation of the CubeCamera's component cameras are upside down. I tried tinkering around with these orientations in the THREE.js source code but only made things worse.
So, is there a correct way to use CubeRefractionMapping with CubeCamera? or a workaround?
r73
I found a workaround: When assigning the envMap to the material, use THREE.BackSide.
var sphereMaterial = new THREE.MeshBasicMaterial(
{
envMap: myCubeCamera.renderTarget,
side: THREE.BackSide,
refractionRatio: .09
} );
A complete example is here.
Not sure why this works, but it does, and that's what the original poster (me!) wanted.

Outline object (normal scale + stencil mask) three.js

For some time, I've been trying to figure out how to do an object selection outline in my game. (So the player can see the object over everything else, on mouse-over)
This is how the result should look:
The solution I would like to use goes like this:
Layer 1: Draw model in regular shading.
Layer 2: Draw a copy in red color, scaled along normals using vertex shader.
Mask: Draw a black/white flat color of the model to use it as a stencil mask for the second layer, to hide insides and show layer 1.
And here comes the problem. I can't really find any good learning materials about masks. Can I subtract the insides from the outline shape? What am I doing wrong?
I can't figure out how to stack my render passes to make the mask work. :(
Here's a jsfiddle demo
renderTarget = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight, renderTargetParameters)
composer = new THREE.EffectComposer(renderer, renderTarget)
// composer = new THREE.EffectComposer(renderer)
normal = new THREE.RenderPass(scene, camera)
outline = new THREE.RenderPass(outScene, camera)
mask = new THREE.MaskPass(maskScene, camera)
// mask.inverse = true
clearMask = new THREE.ClearMaskPass
copyPass = new THREE.ShaderPass(THREE.CopyShader)
copyPass.renderToScreen = true
composer.addPass(normal)
composer.addPass(outline)
composer.addPass(mask)
composer.addPass(clearMask)
composer.addPass(copyPass)
Also I have no idea whether to use render target or renderer for the source of the composer. :( Should I have the first pass in the composer at all? Why do I need the copy pass? So many questions, I know. But there are just not enough resources to learn from, I've been googling for days.
Thanks for any advice!
Here's a js fiddle with working solution. You're welcome. :)
http://jsfiddle.net/Eskel/g593q/6/
Update with only two render passes (credit to WestLangley):
http://jsfiddle.net/Eskel/g593q/9/
The pieces missing were these:
composer.renderTarget1.stencilBuffer = true
composer.renderTarget2.stencilBuffer = true
outline.clear = false
Now I think I've found a bit simpler solution, from the THREEx library. It pre-scales the mesh so you dont need a realtime shader for it.
http://jeromeetienne.github.io/threex.geometricglow/examples/geometricglowmesh.html

Lights look different in Three.js than 3DS Max

I am using the r65 of Three.js. When I light a scene in 3ds max I then export it as a an obj to load in Three.js. I take a second step and export the model to FBX so I can extract the lighting and load in Three.js. I am noticing that the lights are not as "strong" in Three.js, almost like a multipier should be added to the intensity possibly? Could it be that I am missing some property on the light in Three.js?
Here is what the scene looks like in 3ds Max
Here is what it looks like when it's imported to Three.js
After playing around with settings, after turning on the gammaOutput and gammaInput
So it looks a little better with the gamma output on, but still not what I was hoping it would look like from 3ds max. I created a fiddle but due to the Access-Control-Allow-Origin errors I couldn't figure out how to get the fiddle to work, but hopefully the code there will help see what I am trying to do.
// scene
scene = new THREE.Scene();
renderer = new THREE.WebGLRenderer();
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
renderer.gammaOutput = true;
renderer.gammaInput = true;
container.appendChild(renderer.domElement);
loader = new THREE.OBJMTLLoader();
var modelFilePath = "http://goo.gl/ecHpSf?gdriveurl";
var materialFilePath = "http://goo.gl/bZWZEA?gdriveurl";
loader.load(modelFilePath, materialFilePath, function (object) {
materials.push.apply(materials, object.children);
scene.add(object);
object.position.set(0, 0, 0);
});
// setup lighting
var light = new THREE.PointLight(0xffffff, 1);
light.position = new THREE.Vector3(32.2274, 54.6139, 38.2715);
light.distance = 103.74199676513672;
light.intensity = 1;
scene.add(light);
Can anyone suggest anything that might help, it seems like I am close. Thanks!
Do check out material specular component. R65 changed a bit specular component
computation: #4636 (WebGLRenderer: Specular component implementation)
I've got similar problem implementing A3dsViewer 3ds converter to the three.js.
Try to export/save 3ds file and do conversion with the A3dsViewer to the three.js
maybe such workflow will help.
Additionally maybe such settings can help:
renderer.gammaInput = false; // do false
renderer.gammaOutput = true;
After further experimenting I have found that 3ds max has values set for far attenuation start/end. As far as I can tell, there is no way to export this value into Three.js since far attenuation [End] == Distance. Doing a search, it looks like I am limited by the values the light source takes in Three.js. I will follow this up with another post on SO.

Three.js lightMap causes an error WebGLRenderingContext: GL ERROR :GL_INVALID_OPERATION

I'm loading a jpeg file for light map
var texture = new THREE.ImageUtils.loadTexture("textures/metal.jpg");
Then I apply the texture to THREE.MeshPhongMaterial
var frontMaterial = new THREE.MeshPhongMaterial( {
color: 0xfade7e,
specular: 0xffffff,
ambient: 0xaa0000,
lightMap:texture
} )
Full error message is WebGLRenderingContext: GL ERROR :GL_INVALID_OPERATION : glDrawElements: attempt to access out of range vertices in attribute 2
Is here something wrong? An error occures in all browsers. Three.js r.56
As explained by #alteredq in this thread, a LightMap requires a second set of UVs.
The point of lightmaps is that they can live independently of other textures, thus giving other textures chance to be much higher detail. Lightmaps use their own set of UV coordinates (usually auto-generated by some light baking solution, as opposed to artist-created primary UV set).
Using lightmaps with the same UVs as everything else doesn't make much sense, as then you could achieve basically the same result for less texture cost simply by baking light map together with color map (this is e.g. what Rage uses, it looks fantastic but needs boatload of textures).
Also lightmaps should be multiplicative, not additive. Big use case for lightmaps are pre-baked shadows and ambient occlusion, so you need to be able to darken things.
So the answer to your question is that geometry.faceVertexUvs[0] contains the usual set of UVs; you need to add to your geometry geometry.faceVertexUvs[1].
three.js r.56
This error become because the Three.js buffers are outdated. When your add some textures (map,bumpMap ...) to a Mesh, you must recompose the buffers and update UVs like this :
ob is THREE.Mesh, mt is a Material, tex is a texture.
tex.needsUpdate = true;
mt.map = tex;
ob.material = mt;
ob.geometry.buffersNeedUpdate = true;
ob.geometry.uvsNeedUpdate = true;
mt.needsUpdate = true;
That's all folks !
Hope it's help.
Regards.
Sayris

Three.js custom objLoader geometry lighting

I have this object I'm loading with THREE.objLoader and then create a mesh with it like so:
mesh = new THREE.SceneUtils.createMultiMaterialObject(
geometry,
[
new THREE.MeshBasicMaterial({color: 0xFEC1EA}),
new THREE.MeshBasicMaterial({
color: 0x999999,
wireframe: true,
transparent: true,
opacity: 0.85
})
]
);
In my scene I then add a DirectionalLight, it works and I can see my object, however it's like the DirectionalLight was an ambient one. No face is getting darker or lighter as it should be.
The object is filled with the color, but no lighting is applied to it.
If someone can help me with that it would be much appreciated :)
What could I be missing ?
Jsfiddle here: http://jsfiddle.net/5hcDs/
Ok folks, thanks to Maƫl Nison and mr doob I was able to understand the few things I was missing, being the total 3d noob that I am... I believe people starting to get into the 3d may find useful a little recap:
Basic 3d concepts
A 3d Face is made of some points (Vertex), and a vector called a normal, indicating the direction of the face (which side is the front and which one is the backside).
Not having normals can be really bad, because lighting is applied on the frontside only by default. Hence the black model when trying to apply a LambertMaterial or PhongMaterial.
An OBJ file is a way to describe 3D information. Want more info on this? Read this wikipedia article (en). Also, the french page provides a cube example which can be useful for testing.
Three.js tips and tricks
When normals are not present, the lighting can't be applied, hence the black model render. Three.js can actually compute vertex and face normals with geometry.computeVertexNormals() and/or geometry.computeFaceNormals() depending on what's missing
When you do so, there's a chance Three.js' normal calculation will be wrong and your normals will be flipped, to fix this you can simply loop through your geometry's faces array like so:
/* Compute normals */
geometry.computeFaceNormals();
geometry.computeVertexNormals();
/* Next 3 lines seems not to be mandatory */
mesh.geometry.dynamic = true
mesh.geometry.__dirtyVertices = true;
mesh.geometry.__dirtyNormals = true;
mesh.flipSided = true;
mesh.doubleSided = true;
/* Flip normals*/
for(var i = 0; i<mesh.geometry.faces.length; i++) {
mesh.geometry.faces[i].normal.x = -1*mesh.geometry.faces[i].normal.x;
mesh.geometry.faces[i].normal.y = -1*mesh.geometry.faces[i].normal.y;
mesh.geometry.faces[i].normal.z = -1*mesh.geometry.faces[i].normal.z;
}
You have to use a MeshPhongMaterial. MeshBasicMaterial does not take light in account when computing fragment color.
However, when using a MeshPhongMaterial, your mesh becomes black. I've never used the OBJ loader, but are you sure your model normales are right ?
Btw : you probably want to use a PointLight instead. And its position should probably be set to the camera position (light.position = camera.position should do the trick, as it will allow the light to be moved when the camera position will be edited by the Controls).

Resources