6
votes

I'm trying to define a material to meshes I loaded in from OBJLoader through the following wrapper function:

function applyTexture(src){
    var texture = new THREE.Texture();
    var loader = new THREE.ImageLoader();
    loader.addEventListener( 'load', function ( event ) {
        texture.image = event.content;
        texture.needsUpdate = true;

        // find the meshes from the loaded OBJ and apply the texture to it.
        object.traverse( function ( child ) {
            if ( child instanceof THREE.Mesh ) {
                if(child.name.indexOf("Lens") < 0){
                    child.dynamic = true;

                   child.material = new THREE.MeshLambertMaterial( { color: 0xdddddd, shading: THREE.FlatShading, map : texture } );
                   // also tried:
                   //child.material = new THREE.MeshPhongMaterial( { color: 0x000000, specular: 0x666666, emissive: 0x000000, ambient: 0x000000, shininess: 10, shading: THREE.SmoothShading, map : texture} );
                   // and:
                   //child.material = new THREE.MeshBasicMaterial({map : texture});
                   child.material.map = texture; // won't throw the WebGL Warning, but won't show the texture either;
               } else {
                   // works just fine.
                   child.material = new THREE.MeshPhongMaterial( { color: 0x000000, specular: 0x666666, emissive: 0x000011, ambient: 0x000000, shininess: 10, shading: THREE.SmoothShading, opacity: 0.6, transparent: true } );
               }
            }
        });
    });
    loader.load( src );
}

When the texture has loaded and it's time to apply the material to the mesh, I start getting the following warning on the console:

.WebGLRenderingContext: GL ERROR :GL_INVALID_OPERATION : glDrawElements: attempt to access out of range vertices in attribute 0 

and the mesh itself disappears.

what am I doing wrong here?

UPDATE

As @WestLangley pointed on the comments: Never try to apply texture/materials after things have been rendered. Create the materials before rendering the object to the scene and then change them using:

obj.material.map = texture
2
Does it work if you add the texture to the material from the start, so the first rendering of the mesh includes the texture?WestLangley
@WestLangley A texture is applied when the mesh is loaded and before it's added to the scene and that's when it's failing. When I tried using "child.material.map = texture" I didn't get the WebGL warning, but the texture was not applied. For whatever reason, "child.material = new THREE.MeshLambertMaterial( { color: 0xdddddd, shading: THREE.FlatShading, map : texture } );" applies the texture when changing the renderer from WebGL to Canvas. Full code here: gist.github.com/jrmoretti/81047c9d6821e4bbaac5JayMoretti
In WebGLRenderer, you can't add a texture after the fact. You can change just the texture, though. A work-around is to start with a material with a simple white texture.WestLangley
That makes sense. Inspected each mesh from the loaded .obj material and got this: dropmocks.com/mBtEPg which implies that it's already being started with a texture, and it looks like this when it's loaded: dropmocks.com/mBsyrY . Is there any other way to change just the texture besides obj.material.map / obj.material.lightMap?JayMoretti
Provide a simple live example and I'll have a look. Please make it the simplest example that demonstrates your problem. Code fragments are not getting us anywhere.WestLangley

2 Answers

13
votes

With WebGLRenderer, you can't switch from a material without a texture, to a material with a texture, after the mesh has been rendered once. This is because, without an initial texture, the geometry will not have the necessary baked-in WebGL UV buffers.

A work-around is to begin with a material having a simple white texture.

UPDATE: Alternatively, you can begin with a textureless material, and then set the following flags when a texture is added:

material.needsUpdate = true;
geometry.buffersNeedUpdate = true;
geometry.uvsNeedUpdate = true;

three.js r.58

2
votes

I also got this error while loading a scene from blender. For me the problem was fixed when unwrapping the uv's for each mesh i want to have a texture on.