WebGL three.js cube camera mapping - three.js

after following 3 different guides for cube mapping in three.js, I've always encounered same errors in the console:
" ebGL: INVALID_FRAMEBUFFER_OPERATION: drawElements: attachment has a
0 dimension"
"ebGL: INVALID_FRAMEBUFFER_OPERATION: drawArrays: attachment has a 0
dimension"
"[.WebGLRenderingContext]RENDER WARNING: texture bound to texture
unit 0 is not renderable. It maybe non-power-of-2 and have
incompatible texture filtering or is not 'texture complete'"
Those three errors are repated several time in the console.
Here is a guide and a live example i've tried to emulate:
Guide 1
Live Example
Right now my code is similar to the one in the live example:
cubeCameraBottom1 = new THREE.CubeCamera(0.1, 5000, 512 );
scene.add(cubeCameraBottom1);
var provacylGeometry = new THREE.CylinderGeometry(8, 8, 70, 32, 32);
var provacylinderMaterial = new THREE.MeshPhongMaterial( { envMap: cubeCameraBottom1.renderTarget } );
provaCil = new THREE.Mesh( provacylGeometry, provacylinderMaterial );
provaCil.position.set(0,0,-20);
provaCil.castShadow = true;
cubeCameraBottom1.position = provaCil.position;
scene.add(provaCil);
and this is the render function:
function render()
{
provaCil.visible = false;
cubeCameraBottom1.updateCubeMap( renderer, scene );
provaCil.visible = true;
renderer.render( scene, camera );
}
Where am I going wrong? It looks like the cube camera is not computing textures in the right way.
How can I fix this?
Thanks in advance

In the example they used r60. Just maybe that's the Problem, and maybe this can help you:
https://www.khronos.org/registry/webgl/extensions/WEBGL_lose_context/

Related

Attempts to load a texture show no error but the texture does not display

I have a model, a background sky and a ground surface. Texturing the surface results in no surface.
I've tried the basic approach and come to the conclusion that it is probably that the scene is being rendered before the texture has finished loading. Having searched and found various possible solutions, I have tried several of them, without really understanding how they are supposed to work. None of them has worked. One problem is that it is an old problem and most of the suggestions involve outdated versions of the three.js library.
// Ground
// create a textured Ground based on an answer in Stackoverflow.
var loader = new THREE.TextureLoader();
loader.load('Textures/Ground128.jpg',
function (texture) {
var groundGeometry = new THREE.PlaneBufferGeometry(2000, 2000, 100, 100);
const groundMaterial = new THREE.MeshLambertMaterial({map: texture});
var ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.receiveShadow = true; //Illumination addition
ground.rotation.x = -0.5 * Math.PI; // rotate into the horizontal.
scene.add(ground);
}
);
// This variation does not work either
http://lhodges.users37.interdns.co.uk/me/downloads/Aphaia/Temple.htm
http://lhodges.users37.interdns.co.uk/me/downloads/Aphaia/Temple7jsV0.15b.htm
The first of the above is the complete page in which the ground is a plain billiard table green. The second is the page containing the above code.
There appear to be no error (Last time I tried.)
By the time your texture loads and you add the ground, your scene has already rendered (and there is no other render call).
You need to call renderer.render(scene, camera); after adding the ground to the scene.
// Ground
// create a textured Ground based on an answer in Stackoverflow.
var loader = new THREE.TextureLoader();
loader.load('Textures/Ground128.jpg',
function (texture) {
var groundGeometry = new THREE.PlaneBufferGeometry(2000, 2000, 100, 100);
const groundMaterial = new THREE.MeshLambertMaterial({map: texture});
var ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.receiveShadow = true; //Illumination addition
ground.rotation.x = -0.5 * Math.PI; // rotate into the horizontal.
scene.add(ground);
renderer.render(scene, camera); // <--- add this line
}
);

Three.js: Add a texture to an object just on the outside

I'm very new with Three.js and I'm trying to make a ring:
http://www.websuvius.it/atma/myring/preview.html
I have a background texture ( the silver one ) and another one with a text.
I want the text only on the ring external face.
This is part of my code:
var loader = new THREE.OBJLoader( manager );
var textureLoader = new THREE.TextureLoader( manager );
loader.load( 'assets/3d/ring.obj', function ( event ) {
var object = event;
var geometry = object.children[ 0 ].geometry;
var materials = [];
var backgroundTexture = textureLoader.load('img/texture/silver.jpg');
backgroundTexture.flipY = false;
var background = new THREE.MeshBasicMaterial({
map: backgroundTexture,
color: 0xffffff
});
materials.push(background);
var customTexture = textureLoader.load('img/text.png');
customTexture.flipY = false;
var custom = new THREE.MeshBasicMaterial({
map: customTexture,
transparent: true,
opacity: 1,
color: 0xffffff
});
materials.push(custom);
mesh = THREE.SceneUtils.createMultiMaterialObject(geometry, materials);
mesh.position.y=-50;
scene.add(mesh);
}, onProgress, onError );
It is possible?
Thanks
The reason behind your issue appears to be in your .obj file. Judging from a quick glance at the texture coordinates stored in the file, the inside of the ring uses the same part of the texture image as the outside of the ring.
Increasing the transparent parts of the image won't help. Neither will the attempts to stop the texture from repeating. Those would help if the texture coordinates were larger than 1 but this is not your case unfortunately.
However, there are several solutions:
Split the object in a 3D modeling software to two objects - outside and inside of the ring - and apply the texture only to the first one.
Adjust the UV coordinates of the object in a 3D modeling software.
Adjust the UV coordinates of the vertices programmatically after loading the object to Three.JS

Threejs Raycasting a Sprite-Canvas Object is inaccurate [duplicate]

I am trying to use THREE.Raycaster to show an html label when the user hover an object. It works fine if I use THREE.Mesh but with THREE.Sprite it looks like that there is a space that increases with the scale of the object.
The creation process is the same for both scenario, I only change the type based on USE_SPRITE variable.
if ( USE_SPRITE ) {
// using SpriteMaterial / Sprite
m = new THREE.SpriteMaterial( { color: 0xff0000 } );
o = new THREE.Sprite( m );
} else {
// using MeshBasicMaterial / Material
m = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
o = new THREE.Mesh(new THREE.PlaneGeometry( 1, 1, 1 ), m );
}
https://plnkr.co/edit/J0HHFMpDB5INYLSCTWHG?p=preview
I am not sure if it is a bug with THREE.Sprite or if I am doing something wrong.
Thanks in advance.
three.js r73
I would consider this a bug in three.js r.75.
Raycasting with meshes in three.js is exact. However, with sprites, it is an approximation.
Sprites always face the camera, can have different x-scale and y-scale applied (be non-square), and can be rotated (sprite.material.rotation = Math.random()).
In THREE.Sprite.prototype.raycast(), make this change:
var guessSizeSq = this.scale.x * this.scale.y / 4;
That should work much better for square sprites. The corners of the sprite will be missed, as the sprite is treated as a disk.
three.js r.75

Mesh basic materials not rendering a textured quad

I'm just starting out learning some Three.js. I have got a basic webgl example working.
But now that I want to get a similar example working within the THREE.js framework I have ran into trouble with texturing.
The texture is loaded with createjs preloader.
I have tried appending the htmlImageElement to the document to check that it has loaded before the material is created. And this appears fine. So I don't think my problem is creating the material before the texture has completed loading. As has been the problem for others.
Also I have tested a texture from my previous webgl example and this throws the same error, so I don't think the image used is invalid.
The quad in the example below will render as a blue square ok, but the moment I add my texture to the material is throws the error. GL_INVALID_OPERATION : glDrawElements: attempt to access out of range vertices in attribute 1.
I have little experience with Three.js so I think the problem is around how I create the material, scene or geometry. Though I really have ran out of ideas.
I am using TypeScript.
private createPaper(): THREE.Mesh {
var paperGeo = new THREE.Geometry();
paperGeo.vertices.push(new THREE.Vector3(1, 1, 0));
paperGeo.vertices.push(new THREE.Vector3(3, 1, 0));
paperGeo.vertices.push(new THREE.Vector3(3, 3, 0));
paperGeo.vertices.push(new THREE.Vector3(1, 3, 0));
paperGeo.faces.push(new THREE.Face3(0,1,2));
paperGeo.faces.push(new THREE.Face3(2,3,0));
var img: HTMLImageElement = m.getAsset("paper0");
this.paperTex = new THREE.Texture(img, THREE.UVMapping,THREE.ClampToEdgeWrapping, THREE.ClampToEdgeWrapping,
THREE.LinearFilter, THREE.LinearFilter, THREE.RGBAFormat, THREE.UnsignedByteType, 0);
var paperMaterial = new THREE.MeshBasicMaterial({
map:this.paperTex, color: 0x0000dd, side: THREE.DoubleSide
});
var paper = new THREE.Mesh(paperGeo, paperMaterial);
return paper;
}
At a minimum, you need to specify UVs in geometry.faceVertexUvs[ 0 ]. But first, get it working with THREE.PlaneGeometry.
If you are creating a texture using texture = new THREE.Texture(), you need to set texture.needsUpdate = true; The alternative is to use THREE.ImageUtils.LoadTexture();
three.js r.61

How to repeat the texture map like GL_REPEAT?

I have a house model in my game, and I have some materials for the house geometry. There is a material for the wall of the house, and I have a texture-map-image to show the bricks.
var mat = new THREE.MeshPhongMaterial( {
ambient: 0x969696,
map: THREE.ImageUtils.loadTexture( 'textures/G/G0.jpg' ),
overdraw: true,combine: THREE.MultiplyOperation
} );
In this way above, the texture map appears like GL_CLAMP I want it to show like GL_REPEAT.
What should I do?
If you can not see the images check this.
I have posted a full working example at:
http://stemkoski.github.com/Three.js/Texture-Repeat.html
The relevant part of the code example is:
// for example, texture repeated twice in each direction
var lavaTexture = THREE.ImageUtils.loadTexture( 'images/lava.jpg' );
lavaTexture.wrapS = lavaTexture.wrapT = THREE.RepeatWrapping;
lavaTexture.repeat.set( 2, 2 );
var lavaMaterial = new THREE.MeshBasicMaterial( { map: lavaTexture } );
var lavaBall = new THREE.Mesh( THREE.GeometryUtils.clone(sphereGeom), lavaMaterial );
scene.add( lavaBall );
It's called THREE.RepeatWrapping there. The loadTexture defaults to THREE.ClampToEdgeWrapping (see ctor function from previous link). Don't know if you can use the callback (because this in JS is a bit weird (looks like it points to the created Image, not the created Texture)). Signature:
loadTexture: function ( path, mapping, callback ) {
Better you just name the texture locally and set the wrap modes manually:
var t = THREE.ImageUtils.loadTexture( 'textures/G/G0.jpg' );
t.wrapS = t.wrapT = THREE.RepeatWrapping;
Looks like you're not going far with threejs without looking at the actual code...
Image must be 8x8, 16x16, 32x32, 128x128, 256x256, 512x512 etc.
And all be working.
=)

Resources