Light rays from point light three.js - javascript

Is there a way to see the light rays from a point light in a Three js scene. I have tried fog but it makes the whole objects in the scene the color of fog.
var width = $('#g_pre_emo').width();
var scene = new THREE.Scene();
scene.fog = new THREE.Fog(0xffff00, 0, 10);
var camera = new THREE.PerspectiveCamera(50, width / 500, 0.1, 1000);
var renderer = new THREE.WebGLRenderer({antialias: false});
renderer.setSize(width, 500);
$('#g_pre_emo').append(renderer.domElement);
var intensity = 2.5;
var distance = 5;
var decay = 2.0;
var light = new THREE.AmbientLight(0x404040); // soft white light
scene.add(light);
renderer.shadowMap.Enabled = true;
renderer.setClearColor(0xffffff, 1);
var happyGroup = new THREE.Object3D();
var sadGroup = new THREE.Object3D();
var angryGroup = new THREE.Object3D();
var relaxedGroup = new THREE.Object3D();
scene.add(happyGroup);
scene.add(sadGroup);
scene.add(angryGroup);
scene.add(relaxedGroup);
var c1 = 0xffff00;
var sphere = new THREE.SphereGeometry(0.25, 16, 8);
light1 = new THREE.PointLight(c1, intensity, distance, decay);
light1.add(new THREE.Mesh(sphere, new THREE.MeshBasicMaterial({color: c1})));
scene.add(light1);
happyGroup.position.set(-3, 3, 0);
sadGroup.position.set(3, 3, 0);
angryGroup.position.set(-3, -3, 0);
relaxedGroup.position.set(3, -3, 0);
var happyGeometry = new THREE.SphereGeometry(1, 50, 50);
var happyMaterial = new THREE.MeshNormalMaterial();
var happySphere = new THREE.Mesh(happyGeometry, happyMaterial);
scene.add(happySphere);
happyGroup.add(happySphere);
var sadGeometry = new THREE.SphereGeometry(1, 50, 50);
var sadMaterial = new THREE.MeshNormalMaterial();
var sadSphere = new THREE.Mesh(sadGeometry, sadMaterial);
scene.add(sadSphere);
sadGroup.add(sadSphere);
var angryGeometry = new THREE.SphereGeometry(1, 50, 50);
var angryMaterial = new THREE.MeshNormalMaterial();
var angrySphere = new THREE.Mesh(angryGeometry, angryMaterial);
scene.add(angrySphere);
angryGroup.add(angrySphere);
var relaxedGeometry = new THREE.SphereGeometry(1, 50, 50);
var relaxedMaterial = new THREE.MeshNormalMaterial();
var relaxedSphere = new THREE.Mesh(relaxedGeometry, relaxedMaterial);
scene.add(relaxedSphere);
relaxedGroup.add(relaxedSphere);
renderer.gammaInput = true;
renderer.gammaOutput = true;
camera.position.z = 15;
function render() {
renderer.render(scene, camera);
}
;
render();
animate();
function animate() {
requestAnimationFrame(animate);
}
If i run the above code the i cant see any fog in the scene
the fiddle for above code is
https://jsfiddle.net/bqv5ynbo/1/

Possibly, you can use VolumetricSpotlightMaterial from Jerome Etienne.
For me it worked well for Three.js r71, though I haven't tried it with later revisions.
Example of usage

'Light Rays' aren't an automatically occurring thing.
Typically, light rays are created using advanced pixel shaders (stencil/shadow projection over lit region / volumetric fog) or in simple cases by creating simple alpha-blended polygons with 'ray' textures applied.
A point light is simply a light that does not apply directional calculations during it's shading phase. Instead, only distance based calculations are made.
Good Luck!

Related

How does three.js render video according to spherical UV?

I have a dash streaming video. According to its title, it is a 3*3. Now I can splice the complete video through the THREE,
// 3*3 PlaneGeometry
var geometry = new THREE.PlaneGeometry(400, 200, 3, 3);
const video1 = document.getElementById("videos1");
...................
...................
const texture1 = new THREE.VideoTexture(video3);
texture1.maxFilter = THREE.NearestFilter;
texture1.minFilter = THREE.NearestFilter;
...................
...................
var geometryfaces = geometry.faces;
for (let i = 0; i < geometryfaces.length; i++) {
const faces = geometryfaces[i];
materials[i] = new THREE.MeshBasicMaterial({
map: textures[i],
});
}
var uv = [
new THREE.Vector2(0, 0),
new THREE.Vector2(0, 1),
new THREE.Vector2(1, 1),
new THREE.Vector2(1, 0),
];
// Set the texture coordinates
for (var m = 0; m < geometryfaces.length; m += 2) {
geometry.faces[m].materialIndex = faceId;
console.log(geometry.faces);
geometry.faces[m + 1].materialIndex = faceId;
geometry.faceVertexUvs[0][m] = [uv[2], uv[3], uv[1]];
geometry.faceVertexUvs[0][m + 1] = [uv[3], uv[0], uv[1]];
faceId++;
}
var bufferGeometry = new THREE.BufferGeometry().fromGeometry(geometry);
var material = new THREE.MeshFaceMaterial(materials);
var mesh = new THREE.Mesh(bufferGeometry, material); //网格模型对象Mesh
This way I can get a full flat video, but this video is panoramic and I need to render it on the ball, and I don't know much about the UV of the ball。
I need help. Thank you
picture:enter image description here
picture2:enter image description here
Three.js SphereGeometry automatically creates the UV mapping for you. Since the image you're using is equirectangular, you can just map the image onto the inside of the sphere for the effect you want:
var camera, scene, renderer, vp, sphere;
vp = new THREE.Vector2(window.innerWidth, window.innerHeight);
// Init WebGL stuff
function init() {
// WebGL Renderer
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(vp.x, vp.y);
renderer.domElement.classList.add("canvasWebGL");
// append to DOM
document.body.appendChild(renderer.domElement);
// scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0xe1e1e1);
// camera
camera = new THREE.PerspectiveCamera(55, vp.x / vp.y, 0.05, 100);
// Sphere radius is large enough to surround the camera
let sphereGeom = new THREE.SphereGeometry( 20, 128, 128 );
// Just use your equirect image as the texture
// And render the INSIDE of the sphere, not the outside
const tex = new THREE.TextureLoader().load("https://i.imgur.com/1VECsLy.jpg");
let sphereMat = new THREE.MeshBasicMaterial({
map: tex,
side: THREE.BackSide
});
sphere = new THREE.Mesh(sphereGeom, sphereMat);
scene.add(sphere);
}
function animate(s) {
sphere.rotation.set(
Math.cos(s / 3000), s / 3000, 0
);
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
init();
animate(0);
<script src="https://cdn.jsdelivr.net/npm/three#0.123/build/three.js"></script>
Read more about sphere geometry here: https://threejs.org/docs/?q=material#api/en/geometries/SphereGeometry

Three.js point light shadow not where it shoud be

See this JS fiddle for my code. As you can see, there is a gap between the object and the shadow. This works no problem with spot lights. Anyone have any idea how I can fix this?
Key snippets:
//MATERIAL
var material = new THREE.MeshLambertMaterial();
var terrainMaterial = new THREE.MeshStandardMaterial();
//GEOMETRY
var geometry = new THREE.BoxGeometry(100, 100, 100, 10, 10, 10);
var terrainGeometry = new THREE.PlaneGeometry(10000, 10000, 100, 100);
var mesh = new THREE.Mesh(geometry, material);
mesh.position.z = -500;
mesh.position.x = -100;
mesh.position.y = -50;
scene.add(mesh);
var terrain = new THREE.Mesh(terrainGeometry, terrainMaterial);
terrain.rotation.x = -90 * (Math.PI / 180);
terrain.position.y = -100;
scene.add(terrain);
// pointlight
var light = new THREE.PointLight(0xffffff, 2.0, 1200);
scene.add(light);
var pointLightHelper = new THREE.PointLightHelper(light);
scene.add(pointLightHelper);
light.position.y = 100;
light.target = mesh;
light.castShadow = true;
light.shadow = new THREE.LightShadow( new THREE.PerspectiveCamera( 100, 1, 500, 1000 ) );
light.shadow.bias = 0.0001;
light.shadow.mapSize.width = 512;
light.shadow.mapSize.height = 512;
scene.add(light);
mesh.castShadow = true;
terrain.receiveShadow = true;
The "shadow camera" is actually 6 perspective cameras, each with a 90-degree field-of-view (fov). So if you want to modify the shadow camera, you must not change the fov.
light.shadow = new THREE.LightShadow( new THREE.PerspectiveCamera( 90, 1, 500, 1000 ) );
three.js r.92
Try using a smaller bias value.. try moving the light closer or away and see how that changes things.. try cranking shadow res to 1024 or 2048...

Three.js PointLights not working correctly with Lambert material

I am trying to create a scene lit by PointLights but the lights are not working as expected when using Lambert material. It looks like the lights only render when both lights reach the surface.
When I tried to use Phong material, it renders correctly.
My renderer:
var renderer = new THREE.WebGLRenderer();
renderer.shadowMap.enabled = true;
renderer.shadowMap.renderSingleSided = false;
Plane:
var planeGeometry = new THREE.PlaneGeometry(40, 40, 1, 1);
var planeMaterial = new THREE.MeshLambertMaterial();
var plane = new THREE.Mesh(planeGeometry,planeMaterial);
plane.receiveShadow = true;
Walls:
var boxMaterial = new THREE.MeshLambertMaterial({ color: 0x457dd8 });
var boxGeometry = new THREE.BoxGeometry(9, 2, 0.2, 1, 1, 1);
var box = new THREE.Mesh(boxGeometry, boxMaterial);
box.castShadow = true;
box.receiveShadow = true;
Ambient light
var ambientLight = new THREE.AmbientLight("#999292");
and pointLights:
var pointLight = new THREE.PointLight(0xff0000, 20, 50);
pointLight.position.set(16, 1.5, 15.5);
pointLight.castShadow = true;
What am I doing wrong? I think it may be a bug.
Here is my example: https://jsfiddle.net/aojnmspn/
I am using Three.js R87

Shadow is abnormally-shaped for MeshLambertMaterial in Three.js r76?

Using r70, the shadow shows as expected - r70 example (Shadow it correct shape)
Using r76 however, the shadow is abnormally shaped - r76 example (Shadow is abnormally shaped)
You can see that the shadows on the MeshLambertMaterial on the ground plane are not as expected.
Why is the shadows becoming abnormally shaped?
What needs to be changed to get it working in r76?
Here is the code I am using (same in both example):
var light;
light = new THREE.SpotLight(0xdfebff, 1);
light.position.set(300, 400, 50);
light.castShadow = true;
light.shadowCameraVisible = true;
scene.add(light);
var groundMaterial = new THREE.MeshLambertMaterial({
color: 0xFF0000,
});
plane = new THREE.Mesh(new THREE.PlaneGeometry(500, 500), groundMaterial);
plane.rotation.x = -Math.PI / 2;
plane.receiveShadow = true;
plane.castShadow = false;
scene.add(plane);
var boxgeometry = new THREE.CubeGeometry(100, 100, 100);
var boxmaterial = new THREE.MeshLambertMaterial({
color: 0x0aeedf
});
var cube = new THREE.Mesh(boxgeometry, boxmaterial);
cube.castShadow = true;
cube.position.x = 0;
cube.position.y = 100;
cube.position.z = 0;
scene.add(cube);
webglRenderer = new THREE.WebGLRenderer({ alpha: true });
webglRenderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
webglRenderer.domElement.style.position = "relative";
webglRenderer.shadowMapEnabled = true;
webglRenderer.shadowMapSoft = true;
The first thing to do is to add a shadow camera helper so you can see what is going on:
light.shadowCameraHelper = new THREE.CameraHelper( light.shadow.camera );
scene.add( light.shadowCameraHelper );
It is clear that the shadow camera frustum is clipping the shadow.
Starting in three.js r.76, the shadow camera frustum is automatically set so it more closely matches the spotLight field-of-view.
If you would like to override that, you can specify a custom shadow frustum like so:
// custom shadow frustum
light.shadow = new THREE.LightShadow( new THREE.PerspectiveCamera( 30, 1, 200, 700 ) );
updated fiddle: http://jsfiddle.net/ef4r5s76/5/
three.js r.76/r.77

THREEJS No shadow casted

so the problem is straightforward. No shadow in the scene.
At first I thought it was caused by the imported JSON format 3D models, so I added a basic cube in the middle of the scene, still not working.
Light
centerLight = new THREE.SpotLight('#fff',3);
centerLight.castShadow = true;
centerLight.shadowMapWidth = 1024;
centerLight.shadowMapHeight = 1024;
centerLight.shadowCameraNear = 500;
centerLight.shadowCameraFar = 4000;
centerLight.shadowCameraFov = 30;
centerLight.position.set(0,20,0);
centerLight.add(new THREE.Mesh(new THREE.SphereGeometry(1, 16, 8), new THREE.MeshBasicMaterial({
color: '#00fa00',
})));
scene.add(centerLight);
Cube
var shadowMakerGeo = new THREE.BoxGeometry(1,1,1);
var shadowMakerMar = new THREE.MeshLambertMaterial({color:'#000'});
var shadowMaker = new THREE.Mesh(shadowMakerGeo,shadowMakerMar);
shadowMaker.position.set(0,9,0);
shadowMaker.castShadow = true;
scene.add(shadowMaker);
Plane used to let the shadow cast on
var planeGeo = new THREE.PlaneBufferGeometry( 50, 50);
var planeMar = new THREE.MeshLambertMaterial({color:'#fff'});
plane = new THREE.Mesh(planeGeo,planeMar);
plane.receiveShadow = true;
plane.rotation.x = -Math.PI / 2;
scene.add(plane);
And I already did this:
renderer.shadowMapEnabled = true;
All Code here https://github.com/ZZYW/is_shame_necessary_website/blob/master/static/js/homepage/navigation.js

Categories