The problem:
Ok i'm trying draw a few planes with three.js and one of these have a texture but is not drawed when i use WebGLRenderer(), if i change the renderer by CanvasRenderer(), draw the texture, the problem is with WebGL/Three.js.
The error:
Firefox console error: "WebGL: drawElements: bound vertex attribute buffers do not have sufficient size for given indices from the bound element array"
UPDATE
Google chrome error: "[.WebGLRenderingContext]GL ERROR :GL_INVALID_OPERATION : glDrawElements: attempt to access out of range vertices in attribute 1"
The Code:
//scene-camera
var scene = new THREE.Scene ();
var camera = new THREE.PerspectiveCamera (90, window.innerWidth/window.innerHeight, 1, 1000);
camera.position.z = 600;
camera.updateMatrixWorld (true);
scene.add (camera);
//renderer
var renderer = new THREE.WebGLRenderer ();
renderer.setSize (window.innerWidth, window.innerHeight);
document.body.appendChild (renderer.domElement);
//geometry
var geometryPlane = new THREE.PlaneGeometry (600, 400);
//textures
var textureWall1 = THREE.ImageUtils.loadTexture ('textures/wall1.jpg');
textureWall1.anisotropy = renderer.getMaxAnisotropy();
//materials
var materialWall1 = new THREE.MeshBasicMaterial ({map: textureWall1});
//objets-plane
var plane = new THREE.Mesh (geometryPlane, materialWall1);
//vectors
var vecX = new THREE.Vector3(1, 0, 0);
var vecY = new THREE.Vector3(0, 1, 0);
var vecZ = new THREE.Vector3(0, 0, 1);
var vec0 = new THREE.Vector3(0, 0, 0);
//add scene-camera position of the objects
scene.add (plane);
var render = function (){
//translate
plane.translateOnAxis (vecZ, 300);
renderer.render (scene, camera);
}
render ();
I think is a problem with de resolutions of the picture and the plane... but i already have try change it, but it still with the same result, if you need, the resolutions are:
Wall1.jpg (598, 398)px...
Thanks for any help!
PD: this isn't all code, the rest is others planes and materials (colors)
Related
I'm using Three.js to apply a displacement map to a simple plane. The displacement applies successfully, but the lighting is wrong, as if all the normals remain unchanged. The result is a surface with the right shape that's lit as if it were flat.
displacement map:
result:
How can I fix this to properly change the lighting?
Here is the relevant bit of code:
// shortened from actual code - please excuse any small typos
var renderer = new THREE.WebGLRenderer();
renderer.setSize(500, 250);
var scene = new THREE.Scene();
var light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(100, 100, 100);
var ambient = new THREE.AmbientLight(0xffffff, 0.2);
scene.add(light);
scene.add(ambient);
var camera = new THREE.PerspectiveCamera(60, 2, 1, 20000);
var geometry = new THREE.PlaneBufferGeometry(100, 100, 1000, 1000);
geometry.rotateX(-Math.PI / 2);
var material = new THREE.MeshPhongMaterial();
var textureLoader = new THREE.TextureLoader();
var texture = textureLoader.load('circlemap.png');
material.displacementScale = 20;
material.displacementMap = texture;
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
// ... later
renderer.render(scene, camera)
edit: when I set flatShading: true in the material, the normals are updated correctly, but look bad (because of the flat shading):
You're going to have to pass a normalMap along with your displacementMap.
See this demo, when normalScale = 0 it's the equivalent of having no normalMap, and you can see that the reflections don't follow the displacement, only the default topography. However, when normalMap is 1, then the reflections do respect the displacement.
You need to generate a normalMap.
I'm using THREE.Plane to clip my STL model.
localPlane = new THREE.Plane( new THREE.Vector3( 0, -1, 0 ), 4);
.
.
.
material = new THREE.MeshPhongMaterial( {
color: 0xffffff,
side: THREE.DoubleSide,
clippingPlanes: [
localPlane,
],
clipShadows: true
} );
It's working; but the problem is that the whole object's top is clipped by this infinity sized plane. I want it to clip just a small part of it (It seems that there is no way to scale THREE.Plane)
I also tried using ThreeCSG.js but it seems inconvenient with STL objects!
Here is what I get:
Yes, the removal of the intersection of clipping planes is supported in three.js. You can use a pattern like this one:
// clipping planes
var localPlanes = [
new THREE.Plane( new THREE.Vector3( - 1, 0, 0 ), 1 ),
new THREE.Plane( new THREE.Vector3( 0, - 1, 0 ), 1 )
];
// material
var material = new THREE.MeshPhongMaterial( {
color: 0xffffff,
side: THREE.DoubleSide,
clippingPlanes: localPlanes,
clipIntersection: true
} );
Also, see the three.js example.
three.js r.85
Edit: Follow WestLangley's advice. I'll leave this her as an alternate though less efficient means of performing the clipping.
Clipping planes are infinite. There's no getting around that. So what can you do? Multiple clipping planes in multiple render passes!
To do this, you'll need to turn off auto-clearing, and do your own manual buffer clearing.
renderer = new THREE.WebGLRenderer();
renderer.autoClear = false;
Now let's say plane1 is the clipping plane you currently have.
material = new THREE.MeshPhongMaterial( {
...
clippingPlanes: [
plane1,
],
clipShadows: true
} );
var myMesh = new THREE.Mesh(geometry, material);
That clips the top half of myMesh when you call render. So you want to work with the remainder.
First, make another plane, plane2, be the inverse of plane1. plane2 will then clip the BOTTOM of myMesh. But if you render one pass using plane1, and another using plane2, then you're back with a full mesh. So you'll need a third clip plane, plane3, which clips only the desired half of myMesh. Putting plane2 and plane3 in the same render pass will result in only 1/4 of myMesh rendering.
var pass1ClipPlanes = [
plane1
],
pass2ClipLanes = [
plane2, // this plane is the inverse of plane 1, so it clips the opposite of plane1
plane3 // this clips the left/right half of the model
];
Then when you go to render, clear the draw buffers first, then call two render passes, updating the clip planes between them.
// clear the draw buffers
renderer.clear();
// clip the top
myMesh.material.clipPlanes = pass1ClipPlanes;
renderer.render(scene, camera);
// clip the bottom and one side
myMesh.material.clipPlanes = pass2ClipPlanes;
renderer.render(scene, camera);
The first pass renders the bottom of the model, and the second pass renders half of the top.
ETA: Example
var renderer, scene, camera, controls, stats;
var cube,
pass1ClipPlanes,
pass2ClipPlanes;
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight,
FOV = 35,
NEAR = 1,
FAR = 1000;
function init() {
document.body.style.backgroundColor = "slateGray";
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
renderer.localClippingEnabled = true;
renderer.autoClear = false;
document.body.appendChild(renderer.domElement);
document.body.style.overflow = "hidden";
document.body.style.margin = "0";
document.body.style.padding = "0";
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(FOV, WIDTH / HEIGHT, NEAR, FAR);
camera.position.z = 50;
scene.add(camera);
controls = new THREE.TrackballControls(camera, renderer.domElement);
controls.dynamicDampingFactor = 0.5;
controls.rotateSpeed = 3;
var light = new THREE.PointLight(0xffffff, 1, Infinity);
camera.add(light);
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0';
document.body.appendChild(stats.domElement);
resize();
window.onresize = resize;
// POPULATE EXAMPLE
var plane1 = new THREE.Plane(new THREE.Vector3(0, -1, 0), 0),
plane2 = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0),
plane3 = new THREE.Plane(new THREE.Vector3(-1, 0, 0), 0);
pass1ClipPlanes = [plane1];
pass2ClipPlanes = [plane2, plane3];
var cubeGeo = new THREE.BoxBufferGeometry(10, 10, 10),
cubeMat = new THREE.MeshPhongMaterial({
color: "red",
side: THREE.DoubleSide
});
cube = new THREE.Mesh(cubeGeo, cubeMat);
scene.add(cube);
animate();
}
function resize() {
WIDTH = window.innerWidth;
HEIGHT = window.innerHeight;
if (renderer && camera && controls) {
renderer.setSize(WIDTH, HEIGHT);
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
controls.handleResize();
}
}
function render() {
renderer.clear();
cube.material.clippingPlanes = pass1ClipPlanes;
renderer.render(scene, camera);
cube.material.clippingPlanes = pass2ClipPlanes;
renderer.render(scene, camera);
}
function animate() {
requestAnimationFrame(animate);
render();
controls.update();
stats.update();
}
function threeReady() {
init();
}
(function() {
function addScript(url, callback) {
callback = callback || function() {};
var script = document.createElement("script");
script.addEventListener("load", callback);
script.setAttribute("src", url);
document.head.appendChild(script);
}
addScript("https://threejs.org/build/three.js", function() {
addScript("https://threejs.org/examples/js/controls/TrackballControls.js", function() {
addScript("https://threejs.org/examples/js/libs/stats.min.js", function() {
threeReady();
})
})
})
})();
I am trying to create a 3d star view, with a movable camera to traverse stars (js objects) using three.js. In searching for something to get me going/started, I found some code (below) and modified it to what seemed 'logically' correct. The code:
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 500);
camera.position.set(0, 0, 100);
camera.lookAt(new THREE.Vector3(0, 0, 0));
var scene = new THREE.Scene();
var geometry = new THREE.Geometry();
// Starlist contains 1600+ stars
for (var i=0;i<oldstarlist.length;i++)
{
// Convert RA/DEC to x,y,z coordinates
var s0 = new Star(oldstarlist[i]['starname'], oldstarlist[i]['constellation'], oldstarlist[i]['RA'], oldstarlist[i]['DEC'], oldstarlist[i]['lightyears']);
var star = new THREE.Vector3();
star.x = s0.coordinates.X;
star.y = s0.coordinates.Y;
star.z = s0.coordinates.Z;
console.log(star.x,star.y,star.z);
geometry.vertices.push( star );
}
var starsMaterial = new THREE.PointsMaterial( { color: 0x888888 } );
var starField = new THREE.Points( geometry, starsMaterial );
scene.add( starField );
renderer.render(scene, camera);
I presumed the 'Points' was correct, and I am still not sure where to place the camera. To be sure, I checked around for any examples and tutorials I could find but found nothing similar to what I am looking for.
A working example can be found on my test site area at this address:
http://theangelfallseries.com/stars/sp/test3js.html
Any help is appreciated.
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!
I am making a THREE.JS game for one of my classes. I am very keen to learn and understand THREE.JS so I followed some of their tutorials and learnt Javascript. I am more of a C# and C++ guy, so the following question may just the result of the lack of my understanding of Javascript.
I wrote the following Object oriented structure for the game.
ObjectEnum = {
Cube: 0,
Sphere: 1,
Cylinder: 2
}
Transform = function () {
var position, rotation, scale;
}
function TransformInit(position, rotation, scale) {
var t = new Transform();
t.position = position;
t.rotation = rotation;
t.scale = scale;
return t;
}
GameObject = function () {
var mesh, geometry, material, transform;
var GameObject = this;
this.init = function (ObjectEnumType, materialShader, transformVector3) {
if (ObjectEnumType == 0) {
geometry = new THREE.BoxGeometry(transformVector3.scale);
}
transform = transformVector3;
material = materialShader;
mesh = new THREE.Mesh(geometry, material);
}
this.getMesh = function () {
return mesh;
}
}
var go = new GameObject();
this.onload = function () {
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var t = TransformInit(new THREE.Vector3(10, 0, 0), new THREE.Vector3(10, 0, 0), new THREE.Vector3(1, 1, 1));
go.init(ObjectEnum.Cube, new THREE.MeshPhongMaterial({
specular: '#a9fcff',
color: '#00abb1',
emissive: '#006063',
shininess: 100
}), t);
var w = go.getMesh();
scene.add(w);
camera.position.z = 5;
console.log(t);
var render = function () {
requestAnimationFrame(render);
renderer.render(scene, camera);
};
render();
}
Apparently, it doesn't render anything on the screen. I used a Debugger, found out that everything has non zero values, no console errors, all THREE.JS scripts are loaded before this one, things are fine in the editor, but nothing on the screen. When, I change it to an simple procedural structure, it works. Is there a problem in my code or is there a JS concept I am missing in the implementation ?
Followed tutorials from here
http://threejs.org/docs/#Manual/Introduction/Creating_a_scene
http://blog.teamtreehouse.com/the-beginners-guide-to-three-js
Doesn't work on IE11, Chrome, Firefox!
you have passed incorrect argument to BoxGeometry. transformVector3 is Vector3 so you should write:
geometry = new THREE.BoxGeometry(transformVector3.scale.x,
transformVector3.scale.y,
transformVector3.scale.z );
position is not assigned to your mesh:
transform = transformVector3;
material = materialShader;
mesh = new THREE.Mesh(geometry, material);
//here
mesh.position.copy(transform.position);