Texture on Sphere fuzzy after version upgrade - javascript

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.

Related

Threejs - Maintain aspect ratio while adding texture map to threejs object

We want to create a 3d shoe designing tool, where you can design patterns and upload them to the shoe.
I am trying to place an image on a Threejs material. I am able to update the map, but the texture is blurry. I am new to Threejs, so I do not have concepts clear. I don't understand if aspect ratio is the issue or something else.
This how I am loading texture:
var texture_loader = new THREE.TextureLoader();
var texture = texture_loader.load( 'https://ik.imagekit.io/toesmith/pexels-photo-414612_D4wydSedY.jpg', function ( texture ) {
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
texture.offset.set( 0, 0 );
texture.repeat.set( 1, 1 );
vamp.material = new THREE.MeshPhongMaterial({
map: texture,
color: new THREE.Color('#f2f2f2'),
shininess: 20,
});
});
This is what I am getting
But the expected behavior should be
If anyone could help, that would be great. Thanks
Here is the link to the Codepen code
The problem is that your UVs are occupying a very small area in texture coordinates. As they are now, it looks like your UVs are taking up this much room (see red area):
And that's why it gives the impression that your texture is blurry. What you need to do is make your UVs take up more space, like this:
There are 2 ways to achieve this.
Scale UVs up: Import your model into Blender, and change the UV mapping of the mesh to occupy more of the [0, 1] range.
Scale texture down: You could get creative with the texture.repeat property and use it to scale down your texture to match your existing UVs. Then you'd need to offset it so it's centered correctly. Something like:
texture.repeat = new THREE.Vector2(10, 10);
texture.offset = new THREE.Vector2(xx, yy);

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.

three.js map mesh.geometry.attributes.uv

I am currently working on a 3D configurator.
So I should be able to import a logo on a FBX object, which normally already have UV coordinates.
The problem is : I am struggling since 3 days ago, trying to import a texture on a mesh but I can't map it using his UVs coordinates.
So, I have a texture with a logo.
When I map it on a simple Cube, no problem, it is working :
But when I try to apply the same texture to my mesh :
The texture is cropped.
So I've been looking inside the mesh json tree and I found it :
So there are uv coordinates, but it seems different from my cube because, when I look to his json, I don't find the same tree which is (on the cube) :
And finally, this is my code :
if(myMesh.name == 'Logo'){
// Texture
var texture = new THREE.TextureLoader().load('img/logoTesla_Verre_green.jpg', function(){
texture.needUpdate = true;
// Material
var material = new THREE.MeshLambertMaterial( {map: texture, morphTargets: true} );
material.needUpdate = true;
// Geometry Cube
var geometry = new THREE.BoxGeometry( 40, 40, 40 );
// Cube
var cube = new THREE.Mesh( geometry, material);
scene.add(cube);
// Duplicate logo mesh for testing
var newGeometry = myMesh.geometry;
var newMesh = new THREE.Mesh( newGeometry, material);
newMesh.position.y = 100;
newMesh.geometry.uvsNeedUpdate = true;
scene.add(newMesh);
});
}
My question is : Should I use the geometry.attributes.uv object to map my texture ? If yes, how to do that ?
Or should I convert these UV coordinates to a geometry.faceVertexUvs ???
Please, help me, I am totally lost :)
Nevermind, it has been solved by exporting the .fbx again.
Now the mapping is working fine !
But I don't know why...
Thank you for your question and answer. I was having the same problem where my custom FBX I imported was only taking the bottom left pixel of the canvas as the color for the whole mesh. (I was using texture = new THREE.CanvasTexture(ctx.canvas); to get my texture).
The issue for me was that the FBX had no UV mapping! How I solved it was I imported the fbx to maya, opened up the UV editor (under the modeling menu mode got to UV->UV editor ) then in the UV editor there was a Create section and I hit one of those options (i chose cylinder) and then exported it with the default fbx settings. I am very grateful this worked.
You can see the result of using a canvas context as a custom FBX texture here:
www.algorat.club/sweater

Three.js: Weird render result

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.

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