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.
Related
I am currently trying to create a mesh that is colored using a datatexture, my initial coloring shows up just fine, but now my next goal is to offset the texture along the y axis. very similar to this example.
http://math.hws.edu/graphicsbook/demos/c5/textures.html
How I create my texture / mesh:
this.colorTexture = new DataTexture(colors, this.frameWidth, frameCount, RGBFormat, FloatType, UVMapping, RepeatWrapping, RepeatWrapping);
const material = new MeshBasicMaterial({
side: FrontSide,
vertexColors: true,
wireframe: false,
map: this.colorTexture
});
this.mesh = new Mesh(geometry, material);
How I attempt to animate the texture using offset:
this.mesh.material.map.offset.y -= 0.001;
this.mesh.material.map.needsUpdate = true;
this.mesh.material.needsUpdate = true;
this.mesh.needsUpdate = true;
I have confirmed that the function I'm using to try to offset is being called during each animation frame, however the visualization itself is not animating or showing changes apart from the initial positioning of the colors I wrote to the texture.
Any help is greatly appreciated :)
The uv transformation matrix of a texture is updated automatically as long as Texture.matrixAutoUpdate is set to true (which is also the default value). You can simply modulate Texture.offset. There is no need to set any needsUpdate flags (Mesh.needsUpdate does not exist anyway).
It's best if you strictly stick to the code from the webgl_materials_texture_rotation example. If this code does not work, please demonstrate the issue with a live example.
I'm working on an app where I visualize ATV trails in a 3d perspective (NAIP imagery draped over elevation data). I am using three.js for the rendering engine.
In the above image, the white line you see is just a THREE.Line instance, where I convert a trails gps coordinates into threejs coordinates. I'd like to add more of 3d perspective to this line. I tried implementing a THREE.TubeGeometry where the path was a THREE.CatmullRomCurve3 using the same Vector3 points as how I built the line you see in the image above. That did not produce a desirable result...
From the many, many THREE examples I have looked at, I really think an extruded geometry would achieve the look I am after... But I cant for the life of me figure out how to extrude a geometry for the line. Any suggestions/thoughts?
UPDATE 1:
Here is my desired look (same trail - no imagery). This image was produced in QGIS using the Q2Threejs plugin
UPDATE 2: Here is a code of how I have attempted to create a tubegeometry. Maybe I am messing something up in there...
// trailVectors are an array of Vector3 - same as ones used to create line
var trailCurve = new THREE.CatmullRomCurve3(trailVectors);
var tubeGeometry = new THREE.TubeGeometry(trailCurve,80,1,15,false);
var material = new THREE.MeshBasicMaterial({color:0x00ff00});
var tubeMesh = new THREE.Mesh(tubeGeometry,material);
var wireframeMaterial = new THREE.LineBasicMaterial({color:0xffffff,lineWidth:2});
var wireframe = new THREE.Mesh(tubeGeometry,wireframeMaterial);
tubeMesh.add(wireframe);
scene.add(tubeMesh);
UPDATE 3
THREE.TubeGeometry(trailCurve,80,4,2,false) per mzartman request
I think that you should be able to achieve what you want with a TubeGeometry. I think the big thing is that your example (from the picture shown) has more than 2 radius segments. That gives it the tubular shape and makes it look sort of like a blob. If you set the radial segment count to 2 (as it's shown below) then I think it would look a lot better.
tubeGeometry = new THREE.TubeBufferGeometry(
[YOUR_PATH_HERE],
params.extrusionSegments, // <--- Edit this for higher resolution on the spline
3, // <--- This defines the height
2, // <--- This 2 keeps 2D (i.e. not a tube!!!!)
true );
var mesh = new THREE.Mesh( geometry, material );
var wireframe = new THREE.Mesh( geometry, wireframeMaterial );
mesh.add( wireframe );
scene.add( mesh );
Update:
I think that you might do better with a material that shows some shadow like the MeshPhong. Also, to do the wireframe you want to add it as an option in the material initialization. Give it a show with the following:
var tubeGeometry = new THREE.TubeGeometry(curve,80,1,2,false);
var material = new THREE.MeshPhongMaterial({color:0x00ff00, wireframe: true});
var tubeMesh = new THREE.Mesh(tubeGeometry,material);
scene.add(tubeMesh);
I'm currently working on my first three js project, and getting quite an education. But, I've hit a wall, and am seeking a generalized outline of what to do.
I have three images that I want to use as background images. I want them to crossfade at a specified interval... let's say every 5 seconds, the background crossfades to the next one. After the last background is displayed, crossfade into the first one, and so forth in a loop.
I've found a few examples where there's crossfading between two objects, like this fiddle, but that seems to depend on having two cameras. I've taken other examples I've found as far as I could, nothing worthy of posting.
I don't understand enough about three, which is why I'm seeking help. If someone could help me define my approach, that would be fantastic. Should I be altering the opacity of my meshes? Doing something with shaders? Something else?
Here, at least, is how I'm adding one background:
camera = new THREE.PerspectiveCamera( 75, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000 );
camera.position.z = 450;
scene = new THREE.Scene();
// Load the background texture
var summerTexture = THREE.ImageUtils.loadTexture( 'tree-animation/images/summer.png' );
summerMesh = new THREE.Mesh(
new THREE.PlaneGeometry(2, 2, 0),
new THREE.MeshBasicMaterial({
map: summerTexture,
}));
summerMesh.material.depthTest = false;
summerMesh.material.depthWrite = false;
backgroundCamera = new THREE.Camera();
summerScene = new THREE.Scene();
summerScene.add(backgroundCamera);
summerScene.add(summerMesh);
Any direction would be most appreciated!
This can be achieved by writing a custom shader and using the mix() or smooth-step() function between the images and add a clock to your render loop to update the shader uniforms to manipulate the transition in your shader over time.
Here is an example of a static blend of textures but can easily intergrated into your own project:
http://stemkoski.github.io/Three.js/Shader-Heightmap-Textures.html
check the frag shader
I use CubeCamera to build a simple reflection model. The setup can be seen on the picture below.
If the camera is close enough to the cube - the reflection looks fine. However, if i move away from the objects - the reflection just gets bigger. See the picture below.
This is not the way i want it. I'd like the reflection to proportionally get smaller. I tried to play with different settings, then I thought this could be achieved using a proper shader program (just squish the cube texture, kind of), so i've tried to mess with the existing PhongShader, but no luck there, i'm too newbie to this.
Also, i've noticed that if i change the width and height of the cubeCamera.renderTarget, i.e.
cubeCamera.renderTarget.width = cubeCamera.renderTarget.height = 150;
i can get the proper dimensions of the reflection, but its position on the surface is wrong. It's visible from the angle presented on the picture below, but not visible if i place the camera straight. Looks like the texture needs to be centered.
The actual code is pretty straightforward:
var cubeCamera = new THREE.CubeCamera(1, 520, 512);
cubeCamera.position.set(0, 1, 0);
cubeCamera.renderTarget.format = THREE.RGBAFormat;
scene.add(cubeCamera);
var reflectorObj = new THREE.Mesh(
new THREE.CubeGeometry(20, 20, 20),
new THREE.MeshPhongMaterial({
envMap: cubeCamera.renderTarget,
reflectivity: 0.3
})
);
reflectorObj.position.set(0, 0, 0);
scene.add(reflectorObj);
var reflectionObj = new THREE.Mesh(
new THREE.SphereGeometry(5),
new THREE.MeshBasicMaterial({
color: 0x00ff00
})
);
reflectionObj.position.set(0, -5, 20);
scene.add(reflectionObj);
function animate () {
reflectorObj.visible = false;
cubeCamera.updateCubeMap(renderer, scene);
reflectorObj.visible = true;
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
Appreciate any help!
Environment mapping in three.js is based on the assumption that the object being reflected is "infinitely" far away from the reflective surface.
The reflected ray used in the environment map look-up does not emanate from the surface of the reflective material, but from the CubeCamera's center. This approximation is OK, as long as the reflected object is sufficiently far away. In your case it is not.
You can read more about this topic in this tutorial.
three.js r.58
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).