Texture not showing on ThreeJS PointsMaterial map - javascript

I'm trying to load this image as a map of PointsMaterial with TextureLoader but with no success, it throws no errors, but the texture won't show for some reason. Am I doing something wrong or what?
Code:
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
1,
1000
);
const particleBufferGeometry = new THREE.BufferGeometry();
const positionArray = [];
for (let i = 0; i < 10000; i++) {
positionArray.push((Math.random() * 2 - 1) * 200);
positionArray.push((Math.random() * 2 - 1) * 200);
positionArray.push((Math.random() * 2 - 1) * 200);
}
particleBufferGeometry.setAttribute("position", new THREE.Float32BufferAttribute(positionArray, 3));
const particlePointsMaterial = new THREE.PointsMaterial({
size: 0.3,
map: new THREE.TextureLoader().load("./sparkle.png"),
transparent: true,
});
const particlePoints = new THREE.Points(particleBufferGeometry, particlePointsMaterial);
const renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true,
canvas: document.getElementById("three")
});
renderer.setClearColor(0x000000, 0);
renderer.setSize(
window.innerWidth,
window.innerHeight
);
scene.add(particlePoints);
renderer.render(scene, camera);

Another option is to use animation loop:
body{
overflow: hidden;
margin: 0;
}
<canvas id="three"></canvas>
<script type="module">
import * as THREE from "https://cdn.skypack.dev/three#0.135.0";
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
1,
1000
);
const positionArray = [];
for (let i = 0; i < 10000; i++) {
positionArray.push(new THREE.Vector3().random().subScalar(0.5).multiplyScalar(400));
}
const particleBufferGeometry = new THREE.BufferGeometry().setFromPoints(positionArray);
const particlePointsMaterial = new THREE.PointsMaterial({
size: 3,
map: new THREE.TextureLoader().load("https://threejs.org/examples/textures/sprites/spark1.png"),
transparent: true,
});
const particlePoints = new THREE.Points(particleBufferGeometry, particlePointsMaterial);
const renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true,
canvas: document.getElementById("three")
});
renderer.setClearColor(0x000000, 1);
renderer.setSize(
window.innerWidth,
window.innerHeight
);
scene.add(particlePoints);
renderer.setAnimationLoop(() => { // animation loop
renderer.render(scene, camera);
});
</script>

I found why is this happening. I was passing texture as a map before it loaded.
This is wrong.
const particlePointsMaterial = new THREE.PointsMaterial({
size: 0.3,
map: new THREE.TextureLoader().load("./sparkle.png"),
transparent: true,
});
load() function of TextureLoader has second parameter onLoad that executes when texture loads. So solution is:
new THREE.TextureLoader().load("./sparkle.png", (texture) => {
const particlePointsMaterial = new THREE.PointsMaterial({
transparent: true,
map: texture
});
const particlePoints = new THREE.Points(particleBufferGeometry, particlePointsMaterial);
scene.add(particlePoints);
renderer.render(scene, camera);
});

Related

Conditional Drag Drop using DragControl in three.js

I want to activate/deactivate the DragControls depending on the value of a flag drag_flag, but my approach doesn't work well!
can you please tell me how can I do that properly? thanks in advance.
var drag_flag = true;
function change_drag_flag(){
drag_flag = !drag_flag;
}
var objects = [];
var scene = new THREE.Scene();
let box_geometry = new THREE.BoxGeometry(1, 1, 1);
var material = new THREE.MeshPhongMaterial();
const box = new THREE.Mesh(box_geometry, material);
objects.push(box);
scene.add(box);
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(5, 5, 5);
scene.add(spotLight);
spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-5, 5, 5);
scene.add(spotLight);
var camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.set(0.1, 4, 1);
camera.lookAt(scene.position);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var drag_controls = new THREE.DragControls(objects, camera, renderer.domElement);
if(drag_flag===true){
drag_controls.activate();
drag_controls.enabled = true;
}
else{
drag_controls.deactivate();
drag_controls.enabled = false;
}
renderer.render(scene, camera);
<button type="button" onclick="change_drag_flag()">Change Drag Flag</button>
<script src="https://cdn.jsdelivr.net/npm/three#0.101.1/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.101.1/examples/js/controls/DragControls.js"></script>
You are rendering your scene only once so you don't see the effect of enabling/disabling the controls. I've slightly rewritten your code to make things work:
const objects = [];
const scene = new THREE.Scene();
const box_geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshPhongMaterial();
const box = new THREE.Mesh(box_geometry, material);
objects.push(box);
scene.add(box);
const spotLight1 = new THREE.SpotLight(0xffffff);
spotLight1.position.set(5, 5, 5);
scene.add(spotLight1);
const spotLight2 = new THREE.SpotLight(0xffffff);
spotLight2.position.set(-5, 5, 5);
scene.add(spotLight2);
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.set(0.1, 4, 1);
camera.lookAt(scene.position);
const renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const dragControls = new THREE.DragControls(objects, camera, renderer.domElement);
function toggleDrag() {
dragControls.enabled = !dragControls.enabled;
}
function animate() {
requestAnimationFrame(animate);
if (dragControls.enabled === true) {
dragControls.activate();
} else {
dragControls.deactivate();
}
renderer.render(scene, camera);
}
animate();
body {
margin: 0;
}
<button type="button" onclick="toggleDrag()" style="position:absolute">Change Drag Flag</button>
<script src="https://cdn.jsdelivr.net/npm/three#0.101.1/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.101.1/examples/js/controls/DragControls.js"></script>

Make Image to Particles with Three JS in Next JS

now im learning about Three JS and now im in blocker that my expectation should be like this:
but now my code not shows any view, where my code was like this:
import { useEffect } from "react/cjs/react.development";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
export default () => {
useEffect(() => {
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
1,
1000
);
const canvas = document.querySelector("canvas.background");
let renderer = new THREE.WebGLRenderer({ canvas, antialias: true });
new OrbitControls(camera, renderer.domElement);
const img = new Image();
let texture = new THREE.Texture(img);
img.onload = () => {
texture.needsUpdate = true;
const material = new THREE.PointsMaterial({
size: 20,
map: texture,
blending: THREE.AdditiveBlending,
transparent: true,
depthTest: false,
});
const particle = new THREE.Sprite(material);
particle.scale.x = particle.scale.y = 1;
scene.add(particle);
};
img.src = "/flower.png";
scene.add(camera);
camera.position.z = 3;
const animate = () => {
const elapsedTime = new THREE.Clock().getElapsedTime();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.render(scene, camera);
requestAnimationFrame(animate);
};
animate();
}, []);
return <canvas className="background" />;
};
I tried different answers from forum, but seems doesn't works for me
could you guys help? I'll appreciate
You can't use THREE.PointsMaterial with THREE.Sprite. THREE.PointsMaterial is intended for THREE.Points. Use THREE.SpriteMaterial instead.

How to tween/animate fog three.js

So i am trying to change the fog density by tweening it is this possible because it doesn't seem to change here's my defaults:
var camera, densityFog, colorFog2;
colorFog2 = 0xfee2ed;
densityFog = 0.25;
scene.fog = new THREE.FogExp2(colorFog2, densityFog);
and here is what I've tried using the libs GSAP and tweenjs:
tween = new TWEEN.Tween(scene.fog)
.to({densityFog: 0.02}, 1000 )
.easing(TWEEN.Easing.Exponential.InOut)
.onComplete(function() { }).start();
gsap.to(scene.fog, {
duration: 2,
densityFog: 0.02,
onUpdate: function () {
controls.update();
isZoomed = 0;
controls.enabled = false;
},
});
can anyone point me in the right direction?
This answer uses gsap
Use an object eg. myfog = { value: .5 } and tween its value property to what you desire.
Then in onUpdate, set scene.fog to a new THREE.FogExp2 with the current myfog.value as a parameter.
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;
camera.position.y = 2;
// Init the object and fog here
var myfog = { value: .5 }
scene.fog = new THREE.FogExp2(0x00ff00, myfog.value);
var geometry = new THREE.BoxGeometry(1, 1, 5);
var mat = new THREE.MeshBasicMaterial({
color: 0xff0000
});
var mesh = new THREE.Mesh(geometry, mat);
scene.add(mesh);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x00ff00);
document.body.appendChild(renderer.domElement);
function render() {
renderer.render(scene, camera);
}
function animate() {
requestAnimationFrame(animate);
render();
}
animate();
// This animates the fog
gsap.to(myfog, {
duration: 2,
value: 0.002, // The end value
onUpdate: function() {
// New fog with current myfog value
scene.fog = new THREE.FogExp2(0x00ff00, myfog.value);
},
// These just infinitely repeat the animation
yoyo: true,
repeat: -1,
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.6.1/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r127/three.min.js"></script>

three js shape from transparent image

Hi I'm trying to create a 3d model with the upper and lower sides of a transparent image shape, and the others of single color (yellow in this example)
var texture = new THREE.TextureLoader().load( 'img.png' );
var img = new THREE.MeshBasicMaterial( { map: texture } );
var geom = new THREE.BoxGeometry(25,25,1);
https://jsfiddle.net/k2aoh7um/
I'd like to get this:
how can I do that?
The only way, that I can imagine how to achieve this, is to use THREE.Shape() and THREE.ExtrudeBufferGeometry():
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 1, 2);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x101010);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
var center = new THREE.Vector2();
var starLong = new THREE.Vector2(0, 1);
var starShort = new THREE.Vector2(0, 0.5).rotateAround(center, THREE.Math.degToRad(36));
var angle = THREE.Math.degToRad(72);
var points = [];
for (var i = 0; i < 5; i++) {
points.push(starLong.clone().rotateAround(center, angle * i));
points.push(starShort.clone().rotateAround(center, angle * i));
}
var path = new THREE.Shape(points);
var geom = new THREE.ExtrudeBufferGeometry(path, {
steps: 1,
amount: 0.0625,
bevelEnabled: false
});
geom.rotateX(-Math.PI * 0.5);
var star = new THREE.Mesh(geom, new THREE.MeshBasicMaterial({
color: "orange",
wireframe: true
}));
scene.add(star);
render();
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/92/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

Three.js - Animation is not playing

I have problem with animating object exported via blender plugin from blender to THREE.js. Animation did not start running...
Of course, I tried many combinations of settings when exporting from blender and importing to THREE.js library, but without success.
Here is code, what I think should work. Comment Critical section annotate where is probably some mistake. Link to source JSON is in the example too. Of course, I can provide source *.blend file, if needed...
var tgaLoader = new THREE.TGALoader();
var objectLoader = new THREE.ObjectLoader();
var clock = new THREE.Clock();
var SCREEN_WIDTH = window.innerWidth;
var SCREEN_HEIGHT = window.innerHeight;
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
document.getElementById('container').appendChild(renderer.domElement);
objectLoader.load('//cdn.rawgit.com/PiranhaGreg/files/master/scavenger.json', function (loadedScene) {
scene = loadedScene;
mesh = scene.children[0];
scene.background = new THREE.Color('white');
mesh.material = new THREE.MeshPhongMaterial({ map: tgaLoader.load('//cdn.rawgit.com/PiranhaGreg/files/master/SCA_BODY_V0.TGA') });
hemiLight = new THREE.HemisphereLight('white', 'white', 0.6);
scene.add(hemiLight);
camera = new THREE.PerspectiveCamera(30, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000);
camera.position.set(500, 200, -100);
controls = new THREE.OrbitControls(camera);
controls.target.set(0, 50, 0);
controls.update();
var geometry = new THREE.PlaneBufferGeometry(200, 200);
var material = new THREE.MeshPhongMaterial({ shininess: 0.1 });
var ground = new THREE.Mesh(geometry, material);
ground.rotation.x = - Math.PI / 2;
scene.add(ground);
mesh.scale.set(-1, -1, 1);
// Critical section...
mixer = new THREE.AnimationMixer(mesh);
var sequence = THREE.AnimationClip.CreateFromMorphTargetSequence('animation', mesh.geometry.morphTargets, 25, true);
var animation = mixer.clipAction(sequence);
animation.play();
// End of critital section
animate();
});
window.onresize = function() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
};
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
var delta = 0.75 * clock.getDelta();
mixer.update(delta);
renderer.render(scene, camera);
}
body {
margin: 0px;
overflow: hidden;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/three.js/87/three.min.js"></script>
<script src="//cdn.rawgit.com/mrdoob/three.js/master/examples/js/loaders/TGALoader.js" type="application/javascript"></script>
<script src="//cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js"></script>
<div id="container"></div>
Thanks for any suggestion.
I dug in into animation and noticed that it uses morphTargets. And then I remembered about this example. So, the key moment is to set .morphTarget parameter of a material to true, so, I've applied it to the material in your code snippet and it started to work:
mesh.material = new THREE.MeshPhongMaterial({
map: tgaLoader.load('//cdn.rawgit.com/PiranhaGreg/files/master/SCA_BODY_V0.TGA'),
morphTargets: true
});
Though, I'm not sure, if such an approach is correct, but, at least, it's working )
var tgaLoader = new THREE.TGALoader();
var objectLoader = new THREE.ObjectLoader();
var clock = new THREE.Clock();
var SCREEN_WIDTH = window.innerWidth;
var SCREEN_HEIGHT = window.innerHeight;
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
document.getElementById('container').appendChild(renderer.domElement);
objectLoader.load('//cdn.rawgit.com/PiranhaGreg/files/master/scavenger.json', function (loadedScene) {
scene = loadedScene;
mesh = scene.children[0];
scene.background = new THREE.Color('white');
mesh.material = new THREE.MeshPhongMaterial({ map: tgaLoader.load('//cdn.rawgit.com/PiranhaGreg/files/master/SCA_BODY_V0.TGA'), morphTargets: true });
hemiLight = new THREE.HemisphereLight('white', 'white', 0.6);
scene.add(hemiLight);
camera = new THREE.PerspectiveCamera(30, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000);
camera.position.set(500, 200, -100);
controls = new THREE.OrbitControls(camera);
controls.target.set(0, 50, 0);
controls.update();
var geometry = new THREE.PlaneBufferGeometry(200, 200);
var material = new THREE.MeshPhongMaterial({ shininess: 0.1 });
var ground = new THREE.Mesh(geometry, material);
ground.rotation.x = - Math.PI / 2;
scene.add(ground);
mesh.scale.set(-1, -1, 1);
// Critical section...
mixer = new THREE.AnimationMixer(mesh);
var sequence = THREE.AnimationClip.CreateFromMorphTargetSequence('animation', mesh.geometry.morphTargets, 25, true);
var animation = mixer.clipAction(sequence);
animation.play();
// End of critital section
animate();
});
window.onresize = function() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
};
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
var delta = 0.75 * clock.getDelta();
mixer.update(delta);
renderer.render(scene, camera);
}
body {
margin: 0px;
overflow: hidden;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/three.js/87/three.min.js"></script>
<script src="//cdn.rawgit.com/mrdoob/three.js/master/examples/js/loaders/TGALoader.js" type="application/javascript"></script>
<script src="//cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js"></script>
<div id="container"></div>

Categories

Resources