Hi I am trying to do what seems like simple shading with threejs. I am using the Up and Running book by O'reilly.
Everything was working fine, until I tried to do this:
var shader = THREE.ShaderLib["normal"];
var uniforms = THREE.UniformsUtils.clone(shader.uniforms);
uniforms["tNormal"].texture = normalMap;
uniforms["tDiffuse"].texture = surfaceMap;
uniforms["tSpecular"].texture = specularMap;
This keeps throwing this error:
TypeError: uniforms.normal is undefined
[Break On This Error]
uniforms["normal"].texture = normalMap;
I have been looking around online for a while and am not sure what syntax needs to change to solve this issue.
Any help is appreciated.
I think that should be like:
uniforms["tNormal"] = {
texture: normalMap
};
Same for tDiffuse, tSpecular.
I find that when running your code, after the lines:
var shader = THREE.ShaderLib["normal"];
var uniforms = THREE.UniformsUtils.clone(shader.uniforms);
uniforms is an object with one member: opacity. Thus uniforms["tNormal"] does not yet exist. As Olivia suggested, you could add these in using:
uniforms["tNormal"] = {
texture: normalMap
};
Your error and your code are different. The error reports undefined texture on:
uniforms["normal"].texture = normalMap;
The code you cited says you're using:
uniforms["tNormal"].texture = normalMap;.
I'm working on the same book examples, try this:
var shader = THREE.ShaderLib[ "normalmap" ];
var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
uniforms[ "tNormal" ].texture = normalMap;
uniforms[ "tDiffuse" ].texture = surfaceMap;
uniforms[ "tSpecular" ].texture = specularMap;
uniforms[ "enableDiffuse" ].value = true;
uniforms[ "enableSpecular" ].value = true;
Related
when i used addEventlistener for DOMContentLoaded i got error in my console stating that cannot read property 'addEventListener' of null.
And pls explain me how to solve this typeError?
window.addEventListener('DOMContentLoaded', function(){
var canvas = document.getElementById('canvas');
var engine = new BABYLON.Engine(canvas, true);
engine.enableOfflineSupport = false; // Dont require a manifest file
var createScene = function(){
var scene = new BABYLON.Scene(engine);
scene.clearColor = new BABYLON.Color3.White();
var camera = new BABYLON.ArcRotateCamera("arcCam",
BABYLON.Tools.ToRadians(0),
BABYLON.Tools.ToRadians(0),
10.0,BABYLON.Vector3.Zero(),scene);
camera.attachControl(canvas,true);
var light = new BABYLON.PointLight("PointLight",new BABYLON.Vector3(
0,0,0),scene);
light.parent = camera;
light.intensity = 1.5;
BABYLON.SceneLoader.ImportMesh("","","ShippingContainer.babylon",
scene,function(newMeshes) {
newMeshes.forEach(function(mesh){
mesh.rotation = new BABYLON.Vector3(BABYLON.Tools.ToRadians(
45),0,0);
} );
});
return scene;
}
var scene = createScene();
engine.runRenderLoop(function(){
scene.render();
});
});
Uncaught TypeError: Cannot read property 'addEventListener' of null
Check your HTML file. The script line that link your HTML file with your JS file will be in the head. Move it to the end of the body and this problem will dissappear.
How do we know the end of this process can be done?
material.map = new THREE.Texture( canvas );
material.map.needsUpdate = true;
Because if not then it is complete snapshot is sometime black result
var snapshotData = renderer.domElement.toDataURL(strMime);
What can be do successfully changed material callback?
Thank you :)
You can try putting it inside the onload funtion for checking if the texture is loaded or not
var textureLoader = new THREE.TextureLoader();
var texture = textureLoader.load(texturePath, function()
{
//the code below executes only after the texture is successfully loaded
mesh.material.map = texture;
mesh.needsUpdate = true;
//write the code to be executed after the texture is mapped
})
I hope this is helpful.
I am completely new to Three.JS and cant seem to get my head around getting a skybox to appear in my scene. I'm not getting any errors from my code, which has left me stumped. Any help would be greatly appreciated.
function createSky(){
var imageList = "CubeMap"
THREE.ImageUtils.crossOrigin = '';
var faces = ["HDR0001",
"HDR0002",
"HDR0003",
"HDR0004",
"HDR0005"];
var imgType = ".jpg";
var skyGeo = new THREE.CubeGeometry (500, 500, 500);
var matFacesArray = [];
for (var i = 0; i < 6; i++) {
matFacesArray.push( new THREE.MeshBasicMaterial({
map: THREE.ImageUtils.loadTexture( imageList + faces[i] + imgType ),
side: THREE.BackSide
}));
}
var sky = new THREE.MeshFaceMaterial ( matFacesArray );
var skyBox = new THREE.Mesh ( skyGeo, sky );
scene.add ( skyBox );
}
Where are you watching your log for warnings/errors?
Seems strange you are not getting any feedback since THREE.ImageUtils.loadTexture is deprecated, use TextureLoader.load instead, this warning should show up if you are using a somewhat later version of three js.
Also, what browser are you using? I find that Firefox is usually a bit more generous with showing textures than Chrome for example. This has to do with cross-origin image load and can be a problem when you try to run your code locally.
I'm very new to javascript and EaselJS and I've searched the documentation as well as the questions here and I've learned that my initial problem with my mouse events not working with my bitmaps was because I'm trying to use bitmaps from a filepath on my computer.
I understand now that I need to use img.crossOrigin to allow easeljs to work with these images, but even though I'd added this, I still can't get this to work.
Here's what I have:
function init(){
var canvas = document.getElementById('game'); //assign canvas to variable
var stage = new createjs.Stage(canvas);
var term = new Image();
term.src = 'terminal.png';
term.crossOrigin = "Anonymous";
var oswin = new Image();
oswin.src = 'frame.png';
oswin.crossOrigin = "Anonymous";
var terminal = new createjs.Bitmap(term);
terminal.x = 28;
terminal.y = 36;
terminal.name = "terminal";
stage.addChild(terminal);
var oswindow = new createjs.Bitmap(oswin);
stage.addChild(oswindow);
oswindow.x = 196;
oswindow.y = 5;
oswindow.name = "oswindow";
//hide this bitmap
oswindow.visible = false;
//onclick to unhide the bitmap
terminal.on("click", handleClick);
stage.update();
}
function handleClick(){
oswindow.visible = true;
stage.update();
}
I've added in the crossOrigin and unfortunately, this still doesn't work and I've no idea why because I don't understand cross domain very well despite reading on it. (I'm a beginning programmer)
I work entirely offline right now, just trying to learn, so a way to fix this would be really nice.
I'm using three.js to create a minecraft texture editor, similar to this. I'm just trying to get the basic click-and-paint functionality down, but I can't seem to figure it out. I currently have textures for each face of each cube and apply them by making shader materials with the following functions.
this.createBodyShaderTexture = function(part, update)
{
sides = ['left', 'right', 'top', 'bottom', 'front', 'back'];
images = [];
for (i = 0; i < sides.length; i++)
{
images[i] = 'img/'+part+'/'+sides[i]+'.png';
}
texCube = new THREE.ImageUtils.loadTextureCube(images);
texCube.magFilter = THREE.NearestFilter;
texCube.minFilter = THREE.LinearMipMapLinearFilter;
if (update)
{
texCube.needsUpdate = true;
console.log(texCube);
}
return texCube;
}
this.createBodyShaderMaterial = function(part, update)
{
shader = THREE.ShaderLib['cube'];
shader.uniforms['tCube'].value = this.createBodyShaderTexture(part, update);
shader.fragmentShader = document.getElementById("fshader").innerHTML;
shader.vertexShader = document.getElementById("vshader").innerHTML;
material = new THREE.ShaderMaterial({fragmentShader: shader.fragmentShader, vertexShader: shader.vertexShader, uniforms: shader.uniforms});
return material;
}
SkinApp.prototype.onClick =
function(event)
{
event.preventDefault();
this.change(); //makes texture file a simple red square for testing
this.avatar.remove(this.HEAD);
this.HEAD = new THREE.Mesh(new THREE.CubeGeometry(8, 8, 8), this.createBodyShaderMaterial('head', false));
this.HEAD.position.y = 10;
this.avatar.add(this.HEAD);
this.HEAD.material.needsUpdate = true;
this.HEAD.dynamic = true;
}
Then, when the user clicks any where on the mesh, the texture file itself is update using canvas. The update occurs, but the change isn't showing up in the browser unless the page is refreshed. I've found plenty of examples of how to change the texture image to a new file, but not on how to show changes in the same texture file during runtime, or even if it's possible. Is this possible, and if not what alternatives are there?
When you update a texture, whether its based on canvas, video or loaded externally, you need to set the following property on the texture to true:
If an object is created like this:
var canvas = document.createElement("canvas");
var canvasMap = new THREE.Texture(canvas)
var mat = new THREE.MeshPhongMaterial();
mat.map = canvasMap;
var mesh = new THREE.Mesh(geom,mat);
After the texture has been changed, set the following to true:
cube.material.map.needsUpdate = true;
And next time you render the scene it'll show the new texture.
Here is all the basics of what you have to know about "updating" stuff in three.js: https://threejs.org/docs/#manual/introduction/How-to-update-things