In THREE.js, how can I make textures resolution-independent and render without blurriness? - three.js

I'm trying to apply textures to meshes in THREE.js, but to get an acceptable level of clarity, I am forced to use PNGs much larger than desirable, up to several hundred pixels squared in size. If I were to use something simple such as an eight-by-eight checkered pattern, for example, the smallest resolution possible looks like a bunch of dots.
The code being used for the textures is THREE.ImageUtils.loadTexture("sprites/land1.png");

As shown in this example you need to set the filtering of the texture.
var texture = THREE.ImageUtils.loadTexture( 'texture.png' );
texture.magFilter = THREE.NearestFilter;
texture.minFilter = THREE.LinearMipMapLinearFilter;

Related

simulate separate alpha map in glTF

I have an existing 3D application that was developed back in the days of the ThreeJS r92 that made use of a separate alpha map to simulate holes cut in wooden panels. This allowed re-use of a high quality woodgrain texture across all models, while using easily compressible black and white images to create the 'holes' in the wooden panels.
Now that I have begun migration of the project to the current glTF format, I find that the base color and alpha map now have to be combined. The result for my project is that now each of 130+ wooden panels will need their own "wood grain + alpha" texture, rather than being able to share a single wood grain texture.
From all my research, it seems like there are no obvious options to this situation using glTF.. my question now is - does anyone know of ANY workaround using glTF that allows me to separate the base color texture from the alpha map texture?
At this point the best way ahead sadly seems to be to avoid glTF and go back to using ObjectLoader, which is a pain as the binary objects of glTF are a huge plus.
You could export the GLTF with only the base color. Once imported into Three.js, you can manually assign the black/white texture as the material's .alphaMap property.
// Fetch texture
const texLoader = new THREE.TextureLoader();
const alphaTexture = texLoader.load("path/to/alphaTexture");
gltfLoader.load("path/to/model", function(gltf){
// Find the mesh you want to assign an alphaMap to
const myMesh = gltf.getObjectByName("meshName");
// Now just bind your texture to the alphaMap property
myMesh.material.alphaMap = alphaTexture;
myMesh.material.transparent = true;
});
The docs state that only the green channel is used so it doesn't have to be black and white.

Threejs: repeating texture inside of load for a single canvas render

I am rendering a sphere using a threejs lib for react "import * as THREE from 'three';".
The sphere renders fine, as does the texture.
I have an image that's being loaded just fine, and it wraps the entirety of the sphere.
The question: how can I repeat the image across the sphere? In my specific example, imagine I have an image of half a face. Per hemisphere, I would like to mirror that image, so that I would have two symmetrical faces on each side of the sphere, looking outwards. Brand new to threejs, any help is appreciated!
Maybe set repeat on the Texture.
eg.
// load a texture, set wrap mode to repeat
var texture = new THREE.TextureLoader().load( "textures/water.jpg" );
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set( 4, 4 );

ThreeJS - Scale texture's size down (no repeat - using UV-Coords)

Hello i am new to ThreeJS and texture mapping,
Let's say I have a 3D-Plane with the size of (1000x1000x1). When I apply a texture to it, it will be repeated or it will be scaled, to atleast filling the full plane.
What I try to achieve is, to change the scaling of the picture on the plane at runtime. I want the Image to get smaller and stop fitting the full plane.
I know there is a way to map each face to a part of a picture, but is it also possible to map it to a negative number in the picture, so it will be transparent?
My question is:
I UV-Mapped a Model in Blender and imported it with the UV-Coords into my ThreeJS-Code. Now i need to scale the texture down, like described before. Do I have to remap the UV-Cords or do i have to manipulate the image and add an transparent edge?
Further, will I be able on the same way to move the image on the picture?
I already achieved this kind of usage in java3d by manipulating bufferedImages and drawing them onto transparent ones. I am not sure this will be possible using javascript, so i want to know if it is possible by texture-mapping.
Thank you for your time and your suggestions!
This can be done using mapping the 3d -plane to a canvas ,where the image is drawn (fabric.js can be used for canvas drawings).Inshort set the canvas as texture for the 3d model
yourmodel.material.map = document.getElementById("yourCanvas");
Hope it helps :)
Yes. In THREE, there are some controls on the texture object..
texture.repeat, and texture.offset .. they are both Vector2()s.
To repeat the texture twice you can do texture.repeat.set(2,2);
Now if you just want to scale but NOT repeat, there is also the "wrapping mode" for the texture.
texture.wrapS (U axis) and texture.wrapT (V axis) and these can be set to:
texture.wrapS = texture.wrapT = THREE.ClampToEdgeWrapping;
This will make the edge pixels of the texture extend off to infinity when sampling, so you can position a single small texture, anywhere on the surface of your uv mapped object.
https://threejs.org/docs/#api/textures/Texture
Between those two options (including texture.rotation) you can position/repeat a texture pretty flexibly.
If you need something even more complex.. like warping the texture or changing it's colors, you may want to change the UV's in your modeller, or draw your texture image into a canvas, modify the canvas, and use the canvas as your texture image, as described in ArUns answer. Then you can modify it at runtime as well.

THREE.ShaderMaterial is seen inverted by the shadow Camera

I have a mesh that i am loading from 3d studio max into three.js. I modified three.js to hold another typed array for the binormal data. It all seems to be working fine and dandy until shadows are involved. For some reason, the shadow map is wrong, and it seems as if its rendering the mesh with faces flipped.
In this example, the shadows are showing up correctly on the floor, because the renderer has
.shadowMapCullFace = THREE.CullFaceBack
http://dusanbosnjak.com/test/webGL/new/StojadinCeo/stojadinCeo.html
I can get other shadows to show up on my shader, but self shadowing leads to horrible artifacts, and the shadow that my mesh casts on other meshes is always inverted.
I've tried reversing the order in which the face indecis come in, (acb instead of abc), which flips the faces. This creates proper shadow cast, but the mesh shows flipped.
What im thinking of doing at the moment is exporting a flipped mesh, and reversing the cull order in the shaderMaterial, but it would be wonderful to find out why this is happening.
I basically connected the phong and shadow mapping shader chunks with what i've had.
edit
Here is an updated scene with some shadow casters and receive shadows on imported meshes
http://dusanbosnjak.com/test/webGL/new/StojadinCeo/stojadinCeo2.html
light = new THREE.SpotLight(0xaaaaaa);
light.position.set(10,10,10);
light.shadowCameraVisible = true;
light.shadowDarkness = .5;
light.castShadow = true;
light.shadowCameraNear = 1;
light.shadowCameraFar = 250;
light.shadowCameraFov = 57;
light.shadowMapWidth = 2048;
light.shadowMapHeight = 2048;
scene.add(light);
the rest of the meshes just have receiveShadow and castShadow set to true
The shadow shows on the shaderMaterial (i copied the shadowfrag chunk)
THREE.Mesh() with THREE.CubeGeometry() both casts shadows and receives shadows properly, but the shadow cast by the shaderMaterial mesh is inverted.
I can't really isolate this to 50 lines of code as it's a whole import/export process from max.
I don't understand why would the shadow camera render this one particular mesh inverted, while the normal camera renders it correctly, if that is what is happening?
You can zoom out and move the car using wasd
Unless you changed the default settings in three.js, only back-faces cast shadows. A work-around is to set:
renderer.shadowMapCullFace = THREE.CullFaceBack;
or
renderer.shadowMapCullFace = THREE.CullFaceNone;
But these options can lead to other issues.
The best approach is to make sure every mesh has depth. Avoid planes, like the car roof.
For example, you can add an interior liner to the car roof to give it depth.
Shadow mapping in WebGL can be tricky, so read all you can about it so you will be familiar with the issues involved.
three.js r.66

Not all particles are transparent (single material)

My particles are not all rendering as transparent. In the below image you can see that some of the images are surrounded by a box of the background color (clip images behind them), while others are not (do not clip images behind them).
This is the PNG file I'm using:
I load the image and create the material like this:
cimage = THREE.ImageUtils.loadTexture( '/models/candy/c1.png' )
cmat = new THREE.ParticleSystemMaterial
size: 100
map: cimage
transparent: true
Why are the particles not all transparent?
I've found this related question but none of the solutions are really want I want:
depthWrite/depthTest = false: I want the particles to affect the depth, they should be overlapped correctly.
sortParticles = true: only works if one particlesystem is present, the squares still appear for other particle systems
alphaTest = 0.5: this comes closest, but the borders of the images are either not clean, or still have a background color.
You need to sort the particlesystem to get correct transparent levels.
particlesystem.sortParticles = true
When you have multiple particlesystems that are viewed together, then you have 3 options:
play around with the alphaTest property because that discards fragments that have an alpha less then defined
You can do is combine both particles systems and give it another shadermaterial. This makes it possible to sort them again as one.
The last option is to write your own postplugin in webglrenderer. (this is difficult)

Resources