I'm adding the HDRI with:
import {RGBELoader} from './RGBELoader.js'
new RGBELoader().load('./assets/images/brown_photostudio_01_1k.hdr', function (texture) {
texture.mapping = THREE.EquirectangularReflectionMapping
scene.environment = texture
})
My objects are too bright. How can I dim down the light coming from this HDRI?
How can I dim down the light coming from this HDRI?
Assuming you use MeshStandardMaterial or MeshPhysicalMaterial, try it with modulating the envMapIntensity material property.
Related
I have a simple Cube with a PBR Material. Used maps are color, metalness, roughness, bump. When I export the scene via this code, the exported glb is missing all maps but the color. Is this a bug in ThreeJS?
e = new THREE.GLTFExporter();
e.parse(STAGE.scene.mesh, (glb) => {
let blob = new Blob([glb], { type: "application/octet-stream" });
let d = document.createElement('a');
d.href = window.URL.createObjectURL(blob);
d.download = "orbis.glb"
document.body.appendChild(d);
d.click();
document.body.removeChild(d);
}, {binary: true});
You should use different textures. The reason for this is the gltf specification:
gltf uses a normalMap instead of a bumpMap, so bumpMaps are not exported
metalnessMap and roughnessMap are only exported if they are the same texture because gltf uses a single texture for both (see https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#metallic-roughness-material and https://github.com/mrdoob/three.js/issues/14940 for a feature request to merge those textures in the exporter)
I'm making a Three.js scene in which I have stars object and I would like to be able to make them "glow".
By glow I mean make them really emit light not just put a "halo" effect around them.
I tried to put a PointLight object at the same position as the star, this make light emit from the object but as you can see, it doesn't make the object "glow" which make a weird effect.
My current code looks like this:
class Marker extends THREE.Object3D {
constructor() {
super();
// load obj model
const loader = new OBJLoader();
loader.load(
"https://supersecretdomain.com/star.obj",
object => {
object.traverse(child => {
if (child instanceof THREE.Mesh) {
// child.material.map = texture;
child.material = new THREE.MeshLambertMaterial({
color: 0xffff00
});
child.scale.set(0.01, 0.01, 0.01);
}
});
this.add(object);
}
);
const light = new THREE.PointLight(0xffff00, 0.5, 5);
this.add(light);
}
}
Any idea of how to do this ? ;)
Adding a point light to the star is the correct way to make other objects be affected by its light. To make the star itself shine, you can set the emissive color of the material to something other than black (for best results, you probably want it to be the same color as the light).
In addition to setting up your light, and setting the material emissive property as mentioned by Jave above..
You might want to look into the THREE PostProcessing examples.. Specifically Unreal Bloom pass... If you can get that working, it really sells the effect.
https://threejs.org/examples/webgl_postprocessing_unreal_bloom.html
Notice how the highlight glow actually bleeds into the scene around the object...
I need help for getting UV Textures to be rendered correctly in three.js. I've created a model with repeating tile texture in Blender. The tile texture is applied using UV mapping, and it looks like this if it is being rendered correctly:
Render image using Blender
.However, when it is loaded using JSONLoader by three.js, the tiles are just stretched to fill each polygon, giving weird result like this:Screenshot of render using three.js
. I've tried setting THREE.RepeatWrapping in my code but nothing changed:
bodyLoader = new THREE.JSONLoader();
bodyLoader.load('./starofthesea_threejs.json', function(geometry, materials) {
mainBodyMaterials = new THREE.MeshFaceMaterial(materials);
console.log(materials);
mainBodyMaterials.wrapS = THREE.RepeatWrapping;
mainBodyMaterials.wrapT = THREE.RepeatWrapping;
mainBodyMaterials.needsUpdate = true;
mainBody = new THREE.Mesh(geometry, mainBodyMaterials);
mainBody.traverse ( function (child) {
if (child instanceof THREE.Mesh) {
child.castShadow = true;
child.receiveShadow = true;
}
});
mainBody.scale.x = mainBody.scale.y = mainBody.scale.z = 1;
geometry.computeBoundingBox();
geometry.computeFaceNormals();
geometry.computeFlatVertexNormals();
scene.add(mainBody);
});
Is there anything wrong in my code, or workaround to get it rendered correctly? All help is deeply appreciated.
Finally I've figured out the problem by myself, where both the Blender model and JS are misconfigured. RepeatWrapping should be applied to texture but not material. I need to study the structure of THREE.MeshFaceMaterial to find the handle for the underlying textures. I need to traverse through the materials to find out all materials with image textures:
mainBodyMaterials = new THREE.MeshFaceMaterial(materials);
for(prop in mainBodyMaterials.materials) {
if(mainBodyMaterials.materials[prop].map != null) {
mainBodyMaterials.materials[prop].map.wrapS = THREE.RepeatWrapping;
mainBodyMaterials.materials[prop].map.wrapT = THREE.RepeatWrapping;
tex.push(mainBodyMaterials.materials[prop].map.clone());
tex[tex_sequence].needsUpdate = true;
tex_sequence++;
}
}
After applying wrapS and wrapT to textures correctly, one of the tile materials get rendered correctly, but 'Texture marked for update but image is undefined' error keep throwing out. I need to clone the texture to get rid of the error, according to another question: Three.js r72 - Texture marked for update but image is undefined?
As there are several materials with repeating tiles, I need to create a global array at the beginning of the JS routine, and push the modified textures one by one when looping through the materials:
var tex = new Array();
var tex_sequence = 0;
After fixing the JS calls, one of the textures are still not working. I forgot that only ONE UV slot is allowed for three.js. I need to unwrap the UVs again under the same UV slot in Blender. Everything works like a charm, and I hope my painful experience can help those who are getting mad by similar problems.
Following method of adding light helper works ok:
var light = new THREE.SpotLight( 0xFFFFFF );
light.position.set(100,100,100);
scene.add(light);
var helper = new THREE.SpotLightHelper( light );
scene.add(helper);
but following will cause helper to be off position:
var wrapper = new THREE.Object3D();
wrapper.position.set(100,100,100);
var light = new THREE.SpotLight( 0xFFFFFF );
wrapper.add(light);
var helper = new THREE.SpotLightHelper( light );
wrapper.add(helper);
scene.add(wrapper);
It seems like helper position is taken from absolute light position to scene, but is then applied from it's wrapper, that means it is actually applied twice a thus doesn't match actual position of the light. In this example, helper would appear on (200,200,200). Same applies for PointLight and probably other light types.
Is it possible to put helpers into wrapper together with light and avoid position problem?
see it demonstrated here: http://jsfiddle.net/wfpxdw37/24/
Light Helpers are just that -- helpers.
They must be added as a child of the scene.
Consider that requirement a feature. :-)
three.js r.69
It seems that setting THREE.FlatShading for a material doesn't work for BufferGeometry. Is it implemented?
I'm creating BufferGeometry with CTMLoader (useBuffers = true) and applying either MeshLambertMaterial or MeshNormalMaterial with shading: THREE.FlatShading.
Three.js still renders everything as SmoothShading.
If I switch to ClassicGeometry (useBuffers = false), everything works as expected. Unfortunately, that would not work for us since our models are huge and that was exactly the reason to use BufferGeometry.
Is it just not implemented or is it very difficult/time-consuming/not-possible to implement?
Thank you in advance for any hints or suggestions. I'm using the latest r58 version.
P.S.
I found a recent Ryan Rix' post on the same topic http://rix.si/2013/04/15/threejs-ctm-and-you/ where he had to switch to ClassicGeometry to make it work.
In three.js r73 flat shading is working with THREE.MeshPhongMaterial for sure. You can use it like this:
geometry = new THREE.BufferGeometry();
//... make your geometry
material = new THREE.MeshPhongMaterial({
color: 0xff0000,
shading: THREE.FlatShading
});
mesh = new THREE.Mesh( geometry, material );
This doesn't work for THREE.MeshLambertMaterial yet. But they are working on it. Check the related issue here on GitHUB.
flatShading does work in MeshPhongMaterial or any other, the property for
flatShading is boolean
flatShading : Boolean
Define whether the material is rendered with flat shading. Default is false.
const PlaneMaterial = new THREE.MeshPhongMaterial({color:'blue',
side:THREE.DoubleSide,
flatShading:true})
Code Snipet