three js envMap using one texture - three.js

I have a code:
var urls = [ 'img/effects/cloud.png','img/effects/cloud.png','img/effects/cloud.png','img/effects/cloud.png','img/effects/cloud.png','img/effects/cloud.png' ];
var textureCube = THREE.ImageUtils.loadTextureCube( urls, new THREE.CubeRefractionMapping );
var cubeMaterial3 = new THREE.MeshBasicMaterial( { color: 0xffffff, envMap: textureCube, refractionRatio: 0.98, reflectivity:0.9 } );
mesh = new THREE.Mesh( wormholeGeom, cubeMaterial3 );
scene.add(mesh);
This successfully works and inserts sphere with refraction map.
But i do not using skybox, but skysphere where is whole sky represented by one texture.
Is the way to make a refraction mapping from one texture?
Not by array of six textures?
I tried many thinks (THREE.ImageUtils.loadTexture,THREE.SphericalRefractionMapping too) but no luck.
Documentation is "TODO".
This is my goal, but with one texture in skydome. There are used 6 textures in square to make sky.

Related

Life like paper in three.js

I am building a game. In my game is a scene where the character is reading a book. I have created pages of that book which should flip around and stuff. Using Three.js It is simple to crate a cube geo with some specs. My problem is that the paper or page representation is like a board. The paper should be floppy and flexible like paper.
That is where I am stuck. I looked into Physi.js but seems to be an overkill. Collision may be something I need in the future so that the pages do not assume the same exact plane, but for now I will settle for life-like. I looked at morphing but am unsure if that is the way to go.
I Have built a fiddle at https://jsfiddle.net/e4hqdjbz/
It is only a single page with orbit controls though.
//PAPER
frontside = new THREE.TextureLoader().load( 'https://images.pexels.com/photos/2837975/pexels-photo-2837975.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260' );
frontside.minFilter = THREE.LinearFilter;
backside = new THREE.TextureLoader().load( 'https://images.pexels.com/photos/1001780/pexels-photo-1001780.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260' );
backside.minFilter = THREE.LinearFilter;
edge = new THREE.TextureLoader().load( );
edge.minFilter = THREE.LinearFilter;
materialArray1= [
new THREE.MeshBasicMaterial( { color: 0xffffff } ), //Right side
new THREE.MeshBasicMaterial( { color: 0xffffff } ), // Left Side
new THREE.MeshBasicMaterial( { color: 0xffffff } ), // Top
new THREE.MeshBasicMaterial( { color: 0xffffff } ), // Bottom
new THREE.MeshBasicMaterial( { map: frontside } ),
new THREE.MeshBasicMaterial( { map: backside } ),
];
var geometry1 = new THREE.BoxGeometry( 23.3, 50, 0.005 );
var paper = new THREE.Mesh( geometry1, materialArray1 );
paper.position.set(0,0,0)
scene.add( paper );
Any thoughts on a direction I should head and why?
When flipping a page or paper, the animation should be more life-like, kinda flexible but not resistant. Adding physics with gravity, density and airflow may be the answer, but not sure.
Create a skinned mesh animation of the exact textured page animation, in Blender, either by you, or a 3d artist... export that animation as (gltf) .glb and load that in your app, and after the load completes, swap out the material.map s to whatever texture you want.

Color a tetrahedron in three.js

In three.js, I'm trying to draw a tetrahedron using THREE.TetrahedronGeometry where each face is a different color. When I use MeshNormalMaterial, each vertex has a different color but the faces are color gradients between the vertexes. This works for a BoxGeometry, but not for TetrahedronGeometry.
I tried using PhongMaterial with shading: THREE.FlatShading but that just gives me black or white faces.
I tried writing my own ShaderMaterial and in the fragment material, I color using the normal vector, but that also gets the gradient affect.
I'm sure I'm missing something obvious, but can't see it...
For versions of three.js prior to r125*, this is how you do it:
var geo = new THREE.TetrahedronGeometry(sphereRadius, 0);
for ( var i = 0; i < geo.faces.length; i ++ ) {
geo.faces[ i ].color.setHex( Math.random() * 0xffffff );
}
var material = new THREE.MeshBasicMaterial({
side: THREE.DoubleSide,
shading: THREE.FlatShading,
vertexColors: THREE.VertexColors
})
var mesh = new THREE.Mesh( geo, material );
So you need THREE.FlatShader, THREE.VertexColors, and then you need to assign the face colors.
For later versions, see how to render a tetrahedron with different texture on each face (using three.js)?.
* THREE.Geometry will be removed from core with r125

Displacement map on BoxGeometry only moves edges?

I'm just starting to get my bearings with threejs and I'm having an issue using Displacement Maps.
http://codepen.io/jpschwinghamer/pen/BWPebJ
I have a simple BoxGeometry that I'm trying to apply textures to a phong material. All seem to work correctly except for the displacement map. I made sure to add segments to the BoxGeometry instantiation. Is there some bit of magic that I'm missing to make my displacement map work correctly?
Consider this code:
var animate, camera, displacement, geometry, light, light1, map, material, mesh, normal, reflection, renderer, roughness, textureLoader;
renderer = new THREE.WebGLRenderer({
canvas: document.querySelector('canvas'),
antialiased: true
});
renderer.setClearColor(0xfff000);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 0.1, 3000);
window.scene = new THREE.Scene();
light = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(light);
light1 = new THREE.PointLight(0xffffff, 0.6);
scene.add(light1);
textureLoader = new THREE.TextureLoader();
textureLoader.setCrossOrigin("anonymous");
map = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_COL_2K.jpg");
normal = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_NRM_2K.jpg");
roughness = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_GLOSS_2K.jpg");
reflection = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_REFL_2K.jpg");
displacement = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_DISP_2K.jpg");
geometry = new THREE.BoxGeometry(100, 100, 100, 10, 10, 10);
material = new THREE.MeshPhongMaterial({
map: map,
normalMap: normal,
normalScale: new THREE.Vector2(30, -1),
roughnessMap: roughness,
reflectionMap: reflection,
displacementMap: displacement,
displacementScale: 1,
displacementBias: 0
});
mesh = new THREE.Mesh(geometry, material);
mesh.position.set(0, 0, -700);
scene.add(mesh);
animate = function() {
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.01;
requestAnimationFrame(animate);
return renderer.render(scene, camera);
};
animate();
The problem with your displacement map is that there is very little variation in the shades of grey (see it here).
The lowest points should be black and the highest should be white (or the other way around, I forget).
You would also need to have enough verticies for this to affect.
I think though that this map should be assigned to the bump map.
But... you probably don't want to use a bump map and normal map. it's usually one or the other.
But, having a look at the normal map you are loading, it is having no effect because it is all the same color. (see it here), so therefore, it's only the bump map that you need.
Also, MeshPhongMaterial does not seem to have roughnessMap or reflectionMap uniforms/properties, so these are doing nothing.
So basically, you only need to load you map and your displacement map, but put the displacement map on the bump map instead.
Maybe also your roughness image putting it on your specularMap.
EDIT.
Embedding code here does not seem to run because of CORS on the images.
See a FIDDLE HERE
textureLoader = new THREE.TextureLoader();
textureLoader.setCrossOrigin("anonymous");
map = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_COL_2K.jpg");
//normal = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_NRM_2K.jpg");
roughness = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_GLOSS_2K.jpg");
//reflection = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_REFL_2K.jpg");
displacement = textureLoader.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/65874/WoodFlooring044_DISP_2K.jpg");
// Create material
material = new THREE.MeshPhongMaterial({
map: map,
//normalMap: normal,
//normalScale: new THREE.Vector2(30, -1),
//roughnessMap: roughness,
//reflectionMap: reflection,
bumpMap: displacement,
bumpScale: 100,
//displacementBias: 0
specularMap: roughness
});
I believe the problem is that the BoxGeometry only contains 4 vertices per side. When you apply a displacement map, you actually move the positions of the vertices where a normal map would "fake" this on a fragment level.
To solve your problem, I would try with a geometry with a higher number of vertices. A sphere works fine for testing. Then import/generate a box geometry with more vertices.
Hope this helps!

Three.js: Add a texture to an object just on the outside

I'm very new with Three.js and I'm trying to make a ring:
http://www.websuvius.it/atma/myring/preview.html
I have a background texture ( the silver one ) and another one with a text.
I want the text only on the ring external face.
This is part of my code:
var loader = new THREE.OBJLoader( manager );
var textureLoader = new THREE.TextureLoader( manager );
loader.load( 'assets/3d/ring.obj', function ( event ) {
var object = event;
var geometry = object.children[ 0 ].geometry;
var materials = [];
var backgroundTexture = textureLoader.load('img/texture/silver.jpg');
backgroundTexture.flipY = false;
var background = new THREE.MeshBasicMaterial({
map: backgroundTexture,
color: 0xffffff
});
materials.push(background);
var customTexture = textureLoader.load('img/text.png');
customTexture.flipY = false;
var custom = new THREE.MeshBasicMaterial({
map: customTexture,
transparent: true,
opacity: 1,
color: 0xffffff
});
materials.push(custom);
mesh = THREE.SceneUtils.createMultiMaterialObject(geometry, materials);
mesh.position.y=-50;
scene.add(mesh);
}, onProgress, onError );
It is possible?
Thanks
The reason behind your issue appears to be in your .obj file. Judging from a quick glance at the texture coordinates stored in the file, the inside of the ring uses the same part of the texture image as the outside of the ring.
Increasing the transparent parts of the image won't help. Neither will the attempts to stop the texture from repeating. Those would help if the texture coordinates were larger than 1 but this is not your case unfortunately.
However, there are several solutions:
Split the object in a 3D modeling software to two objects - outside and inside of the ring - and apply the texture only to the first one.
Adjust the UV coordinates of the object in a 3D modeling software.
Adjust the UV coordinates of the vertices programmatically after loading the object to Three.JS

Using multiple materials with THREE.CylinderGeometry - create a wheel from cylinder

I want to create a wheel from cylinder (because importing 3D models makes it slower). But I cannot use multiple materials with cylinder geometry. It uses only the first material in an array.
var geometry = new THREE.CylinderGeometry(this.diameterWheel/2,this.diameterWheel/2,this.lastikGenisligi, 20, 4);
var materialArray = [];
materialArray.push(new THREE.MeshBasicMaterial( { color: 0x000000 }));
materialArray.push(new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( '../textures/wheel.png' ) }));
materialArray.push(new THREE.MeshBasicMaterial( { color: 0x0000FF }));
materialArray.push(new THREE.MeshBasicMaterial( { color: 0xFF0000 }));
var material = new THREE.MeshFaceMaterial(materialArray);
var mesh = new THREE.Mesh(geometry, material);
What I want to create is a wheel which will have wheel.png wheel image on upper and bottom sides and black coverage on between them.
You need to loop through each face on the cylinder and tell which of the array materials the face uses.
geometry.faces[a].materialIndex = b;
Where a is the face index. You need to figure out yourself which face is which to choose the correct material through some system, ie. faces 0-10 with one color, etc. This depends on the cylindergeometry parameters. And b is the material index.

Resources