Three.js: Weird render result - javascript

How can I fix the reflection around the cycles?
I got some weird results on my object. I hope the pictures show the problem.
Three.js result
Expected result
loader.load( "model.js", function(geometry){
geometry.computeVertexNormals();
var mesh = new THREE.Mesh( geometry, new THREE.MeshPhongMaterial( {
color: 0xffffff,
specular: 0xffffff,
shininess: 65,
metal: true,
envMap: cubeCamera.renderTarget
}));
scene.add(mesh);
});
I have exported the model with the three.js json exporter from blender. The model has vertices, faces and UVs.

Hmm, this is hard to explain, but basically it is because you are using triangle polygons and your topology is not good.
It is often referred to as "pinching" if I recall correctly.
When modelling for Three.js, it is basically modelling for a game engine and all the same rules need to be followed.
Things you could try to get a better reflection:
Reduce the amount of polygons as it seems you have WAY more polygons than are needed.
Try for a cleaner topology using quads and minimising tris.
Set up smoothing groups
An easy fix would be to use a simple plane in the correct shape with holes cut out as it seems the sides are not really visible anyway. (I am talking about the large flat piece specifically here). I suggest this because I have found that reflections when using MeshPhongMaterial are often not adversely affected by the use of ngons and tris when all the vertices are flat and in the same smoothing group.

Related

Three.js: how to use a plane to cut objects in 2 parts?

I have a complex object, i.e. a box, and I would like to cut it dynamically. This jsFiddle is a very simple example:jsFiddle
Very simple plane
var plane = new THREE.Mesh( geometry, material3 );
plane.rotation.x =1.3; // -Math.PI / 2;
gui.add(plane.rotation, "x", 0.1, Math.PI / 2).name("angle");
gui.add(plane.position, "y", -1, 1).name("h");
scene.add( plane );
I would like to remove from my object the upper part. Just like to cut off a piece from an apple using a knife.
The plane is the knife: In my example, you can play with 2 controls to move the plane up and down or change the angle.
Can you help me to hide the removed part from the object?
You've got two options:
You could use clipping as WestLangley mentioned above.
Clipping does not modify the vertex geometry, it's only visual.
Is non-destructive, so it's good for animating or making constant updates.
Clipping is mostly done with a few planes instead of complex geometry.
You could use a boolean operation with Constructive Solid Geometry.
Boolean does affect the vertex geometry, which can be exported.
Operation is "destructive", so you can't make updates once it's done.
Boolean can be performed with complex geometries, as long as they're "manifold".
Boolean operations require both geometries to be manifold geometries in order to work. This means both meshes have to be closed, without open faces. You cannot use infinitely thin planes, so the example in your JSFiddle wouldn't work. You would need to give each side a little bit of thickness, like using a box with a width of 0.0001 instead of a plane.

Three.JS: render a large map based on different tilesets (Texture Atlas)

Introduction:
I render an isometric map with Three.JS (v95, WebGL Renderer). The map includes many different graphic tilesets. I get the specific tile via a TextureAtlasLoader and it’s position from a JSON. It looks like this:
The problem is that it performs really slow the more tiles I render (I need to render about 120’000 tiles on one map). I can barely move the camera then. I know there are several better approaches than adding every single tile as sprite to the scene. But I’m stuck somehow.
Current extract from the code to create the tiles (it’s in a loop):
var ts_tile = Map.Imagesets[ims].Map.getTexture((bg_left / tw), (bg_top / th));
var material = new THREE.SpriteMaterial({ map: ts_tile, color: 0xffffff, fog: false });
var sprite = new THREE.Sprite(material);
sprite.position.set(pos_left, -top, 0);
sprite.scale.set(tw, th, 1);
scene.add(sprite)
I also tried to render it as a Mesh, which also works, but the performance is the same (of course):
var material = new THREE.MeshBasicMaterial({ map: ts_tile, color: 0xffffff, transparent: true, depthWrite: false });
var geo = new THREE.PlaneGeometry(1, 1, 1);
var sprite = new THREE.Mesh(new THREE.BufferGeometry().fromGeometry(geo), material);
possible solutions in the web:
I know that I can’t add so many sprites or meshes to a scene and I have tried different things and looked at examples, where it works flawless, but I can’t adapt their approaches to my code. Every tile on my map has a different texture and has it’s own position.
There is an example in the official three.js docs: They work with PointsMaterial and Points. In the end they only add 5 Points to the scene, which includes about 10000 “vertices / Images”. docs: https://threejs.org/examples/#webgl_points_sprites
Another approach can be found here on github: https://github.com/YaleDHLab/pix-plot
They create 5 meshes, every mesh includes around 4096 “tiles”, which they build up with Faces, Vertices, etc.
Final question:
My question is, how can I render my map more performant? I’m simply overchallenged by changing my code into one of the possible solutions.
I think Sergiu Paraschiv is on the right track. Try to split your rendering into chunks. This strategy and others are outlined here: Tilemap Performance. Depending on how dynamic your terrain is, these chunks could be bigger or smaller. This way you only have to re-render chunks that have changed. Assuming your terrain doesn't change, you can render the whole terrain to a texture and then you only have to render a single texture per frame, rather than a huge array of them. Take a look at this tutorial on rendering to a texture, it should give you an idea on where to start with rendering your chunks.

Texture on Sphere fuzzy after version upgrade

After upgrading from r67 to r86, our footballs are not very sexy anymore. Did anyone have similar issues in the past?
The code that used to render the spheres nicely, messes up the texture (and some lighting, but I can live with that) in version r86.
The part that creates the spheres:
const material = new THREE.MeshPhongMaterial({ map: texture, transparent: false });
material.alphaTest = 0.5;
const geometry = new THREE.SphereGeometry(radius, res, res);
const mesh = new THREE.Mesh(geometry, material);
Fiddle using r86.
In my comment, I suggested checking the UVs. My suggestion to try different min/mag filter values (http://threejs.org/docs/#api/constants/Textures) was more to correct the image quality, than the texture mapping its self.
What I didn't notice was that your texture was already spherical. The standard linear filter mapped the texture, well, linearly. The weighting/averaging of the linear filter caused the mapping to become compressed toward the top (and bottom, though it wasn't noticeable).
Setting texture.minFilter = THREE.NearestFilter; ditched the weighting/averaging of the texture coordinates, instead mapping to the nearest pixel, which was perfect because of your spherical texture.

How do you use textures with transparency in three.js?

I would like to assemble a group of meshes like this:
The black outlined rectangles represent how I would like to assemble them. I have 8 pieces, 4 edges, and 4 corners, as textures (with transparency). Then, I have a 9th texture that I would like to have underneath the others, and that one is represented by the purple area. The geometries seem to be good, and the texture images are 16x16 pngs. First, I tried the basic approach with just MeshBasicMaterial, and I get my rectangles, but not my textures. Following some advice seen elsewhere on SO I tried something like this:
material = new THREE.MeshBasicMaterial({
transparent: true,
map: texture
});
material.needsUpdate = true;
var materials = [];
materials.push(material);
materials.push(new THREE.MeshBasicMaterial({
color: 0x000000,
wireframe: true,
transparent: true
}));
mesh = THREE.SceneUtils.createMultiMaterialObject(geom, materials);
But this did not work either. I've also tried using the ShaderMaterial but I guess I do not get GLSL well enough yet to make it work. How in the world do I get transparent png textures to map onto ShapeGeometries?

How to get rid of tile outlines when tiling textures to a mesh?

I'm creating a sphere and attaching images to each face of the sphere. In my code I have sphere 12 sections by 6 sections high. I've managed to tile the textures by setting the wrap to repeating and setting the repeat size like so:
var texture = new THREE.ImageUtils.loadTexture( path );
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set( geo_width, geo_height );
return new THREE.MeshBasicMaterial({ map: texture, side: THREE.BackSide, overdraw: true });
It works but now I have these lines between each texture. Is there a way to get rid of them or is there another technique for face-tiling that I should be using?
The lines are the opposite edge of each texture tile appearing at the edges of the geometry. This is what repeating textures do, which is not appropriate in this case.
You don't say what happens when you don't use repeating, but it sounds like what you need to do is adjust the texture coordinate generation so that the coordinates are 0...1 on each tile rather than only on the “0th tile” of the entire sphere.
I don't know Three.js so I can't advise you specifically on its API, sorry.

Categories