texturing ExtrudeGeometry - three.js

I have a problem when I am drawing a canvas texture in THREE.ExtrudeGeometry.
The following image is what I want
But it seems to not work well. It appears a black scene.
This is my project scene.The Texture is work fine to left PlaneGeometry, but no work well to right ExtrudeGeometry.
var shape = new THREE.Shape(points);
var extrudeSettings = {
size: 1,
amount: 8,
bevelEnabled: false,
material: 0,
extrudeMaterial: 1
};
var geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
var canvas = document.querySelector('.heatmap-canvas');
var texture = new THREE.Texture(canvas);
texture.needsUpdate = true;
texture.minFilter = THREE.LinearFilter;
var material = new THREE.MeshLambertMaterial({
map: texture,
color: 0xffffff,
transparent: true,
opacity: 0.7
});
var mesh = new THREE.Mesh(geometry, material);

Related

MeshPhongMaterial or MeshStandardMaterial does not give me the expected output with metallic look

I have the following lights, the ambient light and one PointLight attached to the camera.
this.ambientLight = new THREE.AmbientLight(0xffffff, 0.9);
var pointLight = new THREE.PointLight(0xffffff, 1);
//add to the camera/scene
this.camera.add(pointLight);
this.scene.add(this.ambientLight);
And I'm using the following meshes that I'm trying to give a metallic look, a sphere and a custom mesh that appears like a beam (here the code is simplified)!
//sphere
var sphere = new THREE.Mesh(new THREE.SphereGeometry(10, 10, 10), material2);
//custom mesh
const shape = new THREE.Shape();
shape.moveTo(0,0);
shape.lineTo(0,1);
shape.lineTo(1,1);
shape.lineTo(1,0);
shape.lineTo(0,0);
const extrudeSettings = {
steps: width, // ui: steps
depth: width, // ui: depth
};
var geom = new THREE.ExtrudeGeometry(shape, extrudeSettings);
var beam = new THREE.Mesh(geom , material);
And I've tested with the following materials:
const material = new THREE.MeshPhongMaterial(
{
flatShading: true,
emissive: 'grey',
color: 'grey',
shininess: 150,
side: THREE.DoubleSide,
});
const material2 = new THREE.MeshStandardMaterial({
metalness: 1,
emissive: 'grey',
color: 'grey',
side: THREE.DoubleSide,
flatShading: true,
});
I've tried messing around with the materials settings, but no luck! I want to obtain a metal finishing look, with shadows/depth, ideally using the MeshPhongMaterial!
At the moment, it looks like this:
Am I doing anything wrong with the lightning or with the materials?

three js - How a sphere can shine inside it emitting light to all directions

How to make the sun as a sphere shine inside it and radiate light in all directions?
thanks in advance
I have only this rendering at screen the SUN in the center and a box to see how light reflects to it.
// create a geometry
const radius = 2;
const widthSegments = 100;
const heightSegments = 96;
const geometry = new THREE.SphereBufferGeometry(
radius,
widthSegments,
heightSegments
);
const geometry1 = new THREE.BoxBufferGeometry(3, 13, 3);
//create texture loader
const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load("https://i.ibb.co/3srcxqp/Sol.jpg");
texture.encoding = THREE.sRGBEncoding;
texture.anisotropy = 16;
const material = new THREE.MeshStandardMaterial({
map: texture,
color: "#ffffff",
specular: "#ffffff",
transparent: true,
side: THREE.DoubleSide,
alphaTest: 0.5,
opacity: 1,
roughness: 1,
});
material.alphaMap = texture;
material.alphaMap.magFilter = THREE.NearestFilter;
material.alphaMap.wrapT = THREE.RepeatWrapping;
material.alphaMap.repeat.y = 1;
var material1 = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
mesh = new THREE.Mesh(geometry, material);
const mesh1 = new THREE.Mesh(geometry1, material1);
scene.add(mesh);
scene.add(mesh1);
mesh1.position.set(-10, -10, -10);
mesh1.updateMatrix();

Artifacts on the top and bottom of png textures in THREE.js v76

I'm getting some artifacts on the top and bottom sides on some of my sprites. These are the shaders I am using, if that matters. I'm using v76.
And I'm building these sprites like this:
var object = new THREE.Object3D();
var textureLoader = new THREE.TextureLoader();
textureLoader.load('path/to/image.png', function(texture) {
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.anisotropy = 16;
var geometry = new THREE.PlaneBufferGeometry(15, 15);
var material = new THREE.MeshPhongMaterial({
map: texture,
color: 0xffffff,
transparent: true,
alphaTest: 0.2,
side: DoubleSide,
});
var mesh = new THREE.Mesh(geometry, material);
mesh.castShadow = true;
mesh.receiveShadow = true;
mesh.customDepthMaterial = new ShaderMaterial({
uniforms: { texture: { type: 't', value: this.material.map } },
vertexShader: vertexShader,
fragmentShader: fragmentShader,
});
object.add(mesh);
})
Don't set your textures to wrap with THREE.RepeatWrapping. This can leave artifacts on texture edges meant to be used as sprites.

Three.js self transparency, object should not be see through

Codepen demonstrating the problem
https://codepen.io/anon/pen/GjJpYw?editors=0010
I have 2 meshes, one which contains 2 cubes, and the other which is 1 cube. The mesh with 2 cubes sandwiches the mesh with one cube (so the single cube is in the center). When I set all cubes to transparent but set the opacity of the center cube to 1, I would not expect to be able to see the back cube when looking through the front cube but I can.
I was wondering is there any easy way to fix this? This is a very simplified version of the problem I'm facing so I can't easily split the geometries. I also cannot just set transparent to false since ideally I would like to be able to have the middle cube partially transparent as well. Any suggestions?
var width = window.innerWidth;
var height = window.innerHeight;
var renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(width, height);
document.body.appendChild(renderer.domElement);
var scene = new THREE.Scene();
var cubeGeometry = new THREE.CubeGeometry(100, 100, 100);
var cube = new THREE.Mesh(cubeGeometry);
cube.position.set(0, 25, -200);
var cube2 = new THREE.Mesh(cubeGeometry);
cube2.position.set(0, -25, 200);
cube.updateMatrix();
cube2.updateMatrix();
var singleGeometry = new THREE.Geometry();
singleGeometry.merge(cube.geometry, cube.matrix);
singleGeometry.merge(cube2.geometry, cube2.matrix);
var combinedMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000, opacity: 0.5, transparent: true});
var mesh = new THREE.Mesh(singleGeometry, combinedMaterial);
var cubeGeometry = new THREE.CubeGeometry(200, 200, 200);
var cubeMaterial = new THREE.MeshBasicMaterial({ color: 0x0000ff, opacity: 0.8, transparent: true});
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
scene.add(cube);
scene.add(mesh);
var camera = new THREE.PerspectiveCamera(60, width / height, 1, 1000);
camera.position.z = 500;
var controls = new THREE.OrbitControls(camera);
controls.addEventListener('change', render);
var pointLight = new THREE.PointLight(0xffffff);
pointLight.position.set(0, 300, 200);
scene.add(pointLight);
render();
animate();
function animate() {
requestAnimationFrame( animate );
controls.update();
}
function render() {
renderer.render( scene, camera );
}

Different material on back and frontside of extruded shape

I'm trying to apply different material on front and back sides of extruded shape, but cannot figure out where to put side: THREE.FrontSide and side: THREE.BackSide. Where they should be putted?
My relevant code part is:
var materialFront = new THREE.MeshPhongMaterial({ ambient: 0xffffff, map: frontTexture });
var materialSide = new THREE.MeshPhongMaterial({color: 0xE68A00, ambient: 0xffffff});
var extrusionSettings = {
amount: 10,
bevelEnabled: false,
bevelThickness: 0.2,
bevelSize: 0.2,
bevelSegments: 8,
material: 0,
extrudeMaterial: 1
};
var geometry = new THREE.ExtrudeGeometry(shapes, extrusionSettings);
var materials = [materialFront, materialSide];
var material = new THREE.MeshFaceMaterial(materials);
mesh = new THREE.Mesh(geometry, material);
UPDATE:
According to WestLangley's comment I succeeded in adding the different texture to backfaces:
// ...
var materials = [materialFront, materialSide, materialBack];
// ...
for ( var face in mesh.geometry.faces ) {
if (mesh.geometry.faces[ face ].normal.z == 1) mesh.geometry.faces[ face ].materialIndex = 2;
}
After you create your mesh geometry, and before the first call to render(), you have to change the materialIndex to 2 for the back faces. Then, add a third material in your material array.
You can identify the back faces by their face normals. Face normals for faces on the back of the geometry should all point in the same direction.
three.js r.58
Try using:
var materialFront = new THREE.MeshPhongMaterial({ ambient: 0xffffff, map: frontTexture, side: THREE.FrontSide });
var materialSide = new THREE.MeshPhongMaterial({ color: 0xE68A00, ambient: 0xffffff, side: THREE.BackSide });
even though you should probably lower your ambient contribution and give a color to the FrontSide material.
Then:
var materials = [materialFront, materialSide];
scene.add( THREE.SceneUtils.createMultiMaterialObject( geometry, materials ));

Resources