Using CanvasTexture with a Sprite - javascript

I am upgrading some code that used to work with three.js r61 to three.js r74. I know, it's a big jump, but things are not always as they should be.
One of the remaining things that I still didn't get to work properly is a texture built using a canvas, used in a SpriteMaterial which is then used for a THREE.Sprite.
So far, I did the following:
Changed Texture to CanvasTexture
In SpriteMaterial, commented out the usage of useScreenCoordinates, alignment and sizeAttenuation
I tried various stuff, but it seems like this thing just doesn't display at all. Is there any such example anywhere? I just want to display an artifact that is built in a canvas.
Update: the code below is what I tried so far:
var loader = new THREE.TextureLoader();
loader.load(canvas.toDataURL(), function(texture) {
var material = new THREE.SpriteMaterial({
map: texture,
blending: THREE.AdditiveBlending,
color: me.color,
opacity: me.opacity,
transparent: me.transparent,
visible: me.visible
});
var sprite = new THREE.Sprite(material);
scene.add(sprite);
});

You're quite light on details but here's one good way to do it:
https://jsfiddle.net/_jered/xcej4ec6/
var loader = new THREE.TextureLoader();
loader.load(canvas.toDataURL(), function(d){
// 'd' is the loaded texture
// apply it to the object here
});
Basically, just use the built in Loader classes to load the assets you need, including from canvas. It's important to use Loaders and callbacks because assets will become ready asynchronously, and you need to wait until they're done before you make use of them. In my example, I create the mesh with a placeholder texture, and apply it in the Loader's callback.

Related

ThreeJS TextureLoader is black in .NET blazor application

When using textureloader from three.js in a blazor application. when trying to get a picture on a cube, it just gets displayed in black. I have tried a lot of things including:
new THREE.TextureLoader().load('https://images.pexels.com/photos/2422/sky-earth-galaxy-universe.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500', function (texture) {
var objGeometry = new THREE.SphereBufferGeometry(11, 11, 11);
var objMaterial = new THREE.MeshPhongMaterial({
map: texture,
shading: THREE.FlatShading
});
moonMesh = new THREE.Mesh(objGeometry, objMaterial);
scene.add(moonMesh);
});
Local images that are preloaded don't work, tried with and without callback. Tried another browser.
The console is empty, if I log the texture, it's always define.
Still the sphere is always displayed in black. Maybe a light is missing, although they don't get used in any example. The js is loaded from a blazor page using the following code:
protected override async Task OnAfterRenderAsync(bool firstRender)
{
object[] args = { canvasId };
await JSRuntime.InvokeVoidAsync("threeExample", args); // NOTE: call JavaScript function
}
And the scene and stuff load fine, I can use orbidcontrols, normal cubes with a color texture are visibe. Any ideas?
EDIT:
When using MeshBasicMaterial It works! So I guess I used the wrong type of material to use the texture.
Kind regards

PIXI.JS Newbie, looking for advice and troubleshoot of a textureCache, loader issue

ive ventured into the world of PIXI and JS, new programming language for me, liking the way it is right now but i have an issue.
I am a bit confused with the TextureCache and the loader. If you look at part of my code i try to add 3 different images to the screen. Ive been following the 'Get Started section' of the pixi website. I wanted to add their cat image, which i have, the tileset image (all of it)* and then a tile of the tileset image.
The issue is, i create 3 new sprite instances and the tileset image shows the area ive set for the tile(rocket) when i want it to show the whole tileset. Ive loaded in the tileset iin the cahce and the loader.
Why does tile show the cropped image and not the whole image?
Am i using the cache correctly to just store images?
Am i using the resources method properly to locate the image FROM the cache or the loader?
Is there any point of the cache?
my thoughts**
when you use the rectangle method, it destroys the original image and the cropped version is now tileset1 (the name of my image)?
<html>
<body>
<script src="pixi.js"></script>
<script>
//Aliases
let Application = PIXI.Application,
loader = PIXI.loader,
resources = PIXI.loader.resources,
Sprite = PIXI.Sprite,
Rectangle = PIXI.Rectangle,
TextureCache = PIXI.utils.TextureCache;
let app = new PIXI.Application({
width: 1000,
height: 600,
antialias: true,
transparent: false,
resolution: 1
}
);
//Add the canvas that Pixi automatically created for you to the HTML document
document.body.appendChild(app.view);
TextureCache["tileset1.png","images/3.png"];
//load an image and run the `setup` function when it's done
loader.add(["images/3.png","tileset1.png"]).load(setup);
//This `setup` function will run when the image has loaded
function setup() {
let texture = TextureCache["tileset1.png"];
let rectangle = new Rectangle(96,64,32,32);
texture.frame = rectangle;
//Create the cat sprite, use a texture from the loader
let card = new Sprite(resources["images/3.png"].texture);
let tile = new Sprite(resources["tileset1.png"].texture);
let rocket = new Sprite(texture);
card.scale.set(0.06,0.06);
tile.x=400;
tile.y=400;
rocket.x=100;
rocket.y=100;
//Add the cat to the stage
app.stage.addChild(card);
app.stage.addChild(tile);
app.stage.addChild(rocket);
app.renderer.render(app.stage);
}
</script>
</body>
</html>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/5.2.4/pixi.js"></script>
Is there any point of the cache? - this question seems to be most important from your questions :)
Searching around about "pixi.js" and "TextureCache" gives following answers for example:
https://github.com/pixijs/pixi.js/issues/4053
MySecret commented on May 23, 2017:
the docs has no specs about PIXI.utils.TextureCache
...
englercj commented on May 26, 2017
This is intentional, it is not meant as a public-facing API. It is an internal cache used by some texture creation methods.
https://www.html5gamedevs.com/topic/17788-loader-and-texturecache-tutorial-anywhere/
xerver - Pixi.js Moderator:
Here is the loader: https://github.com/englercj/resource-loader
The code is really well documented, and there are examples on the readme. The pixi examples also use the loader a few times: http://pixijs.github.io/examples/
The TextureCache is an internal mechanism, there is rarely any reason you should even know it exists.
https://www.html5gamedevs.com/topic/25575-pixiloaderresources-or-texturecache/
xerver - Pixi.js Moderator:
Dont do this:
let e = PIXI.utils.TextureCache[player.img];
Instead use the resources the loader loaded for you:
let e = PIXI.loader.resources[player.img].texture;
...
TLDR: Usually TextureCache shouldnt be used directly :)
See also:
this explanation: https://www.html5gamedevs.com/topic/9255-pixijs-caching/?tab=comments#comment-55233
http://pixijs.download/release/docs/PIXI.BaseTexture.html#.addToCache
^ example of usage: https://jsfiddle.net/themoonrat/br35x20j/

Three.js – Applying texture to Collada mesh yields unexpected result

Following the Three.js ColladaLoader example, I've exported a Cinema4D soda
can model (consisting of 4 meshes) to a .dae file. One of the meshes, the body of the can, I want to add a texture to.
In Cinema4D I've already made a texture based on a UV map of the mesh (spherical). However, when I try to apply the texture to the mesh, it simply shows a solid white fill. I've added the entire code in this Codepen. Relevant code below, edited for brevity:
loader = new THREE.ColladaLoader();
loader.load('can.dae', function (collada) {
can = collada.scene;
can.traverse(function (node) {
var textureLoader
if (node.name == 'wrapper') {
textureLoader = new THREE.TextureLoader();
textureLoader.load('wrapper.png', function (texture) {
node.material = new THREE.MeshBasicMaterial({
map: texture
});
node.material.needsUpdate = true;
});
}
});
scene.add(can);
});
Illustration of the result. As you can see, the wrapper of the can isn't the red wrapper.png provided, but a solid white fill. I've tried experimenting with mapping and wrapping modes, but to no avail. Any help very much appreciated!
FYI: I've already ruled out CORS issues.
I added a cube in your loader and gave it that material and it worked.. so the implication is that your can mesh does not have proper UV coordinates assigned to it.. Perhaps it is using an automatic cylindrical mapping in your authoring software which is not exporting it's UVs? What software are you authoring in?
scene.add(new THREE.Mesh(new THREE.BoxGeometry(1,1,1),node.material));
https://codepen.io/manthrax/pen/ePBZbZ?editors=1001

Can we apply custom shaders to three.js objects dynamically

I have a MeshBasicMaterial with VideoTexture. Can I apply custom shaders to the material dynamically. I was able to apply shader to the complete scene using THREE.EffectComposer but what if I want to apply custom filters to a specific element inside the scene. I want to test simple filters like sepia, hue-saturation. Also I must be able to switch between the two without reloading the project.
I did not go with js libraries like seriously.js or glfx.js because it may cause problem at later stages when I will work with three.js objects not having canvas/img/video as map.
videoTexture = new THREE.VideoTexture(video);
videoTexture.minFilter = THREE.LinearFilter;
videoTexture.magFilter = THREE.LinearFilter;
material = new THREE.MeshBasicMaterial({
map: videoTexture,
side: THREE.DoubleSide,
transparent: true,
depthTest: false,
depthWrite: false
});
composer = new THREE.EffectComposer( renderer );
composer.addPass( new THREE.RenderPass( scene, camera ) );
var effect = new THREE.ShaderPass( THREE.SepiaShader );
effect.renderToScreen = true;
composer.addPass( effect );
composer.render();
Edit 1: filter css( https://developer.mozilla.org/en-US/docs/Web/CSS/filter) won't work either as it only changes visual media and hence though it can manipulate final canvas it can not manipulate internal object textures.
THREE.EffectComposer has a .reset function that you could use to wipe it, and then add the new filters you want. So just load the different filters you want to cycle through into an array, then reset and add passes from that array.
EDIT I thought you were talking about changing shaders in the composer. To change shaders on an object, you can create multiple shadermaterials with different shaders but referencing the same texture, and swap the materials out on the object. So you can write a shader that reinterprets the texture colorspace to sepia, one that reinterprets the texture colorspace to bnw, or swizzles hue and saturation with r,g, or b.
Then you swap multiple materials out on the fly. These effects are basic glsl, but if you have trouble writing the shaders, just post another thread with specific problems. If you're a glsl novice, I highly recommend the book of shaders. It's a great, fast, interactive crash course on glsl.
But the solution to your problem is to create multiple shadermaterials, or create one shader material that does everything and then use uniforms to enable/lerp between the different effects.

How to texture animated js model exported from blender ? [Three.js]

I have successfully animated a model in blender using bone animation technique and i have also textured it in blender using uv texturing. Then Using three.js export add-on in blender i have exported the model making sure uv and animation in checked in. However i don't know the technique to load the texture for the animated model. I viewed the morph normal example included in three.js where there is simple color texture is used using Lambert material. I have texture from external file. How do i load the texture. In js animated model file there is location for the texture and it is in same location. But it doesn't load. i used the face material technique as well.
the location for three.js example that i used to modify:
http://threejs.org/examples/webgl_morphnormals.html
Here is my code:
var loader = new THREE.JSONLoader();
loader.load( "bird_final.js", function( geometry, materials ) {
morphColorsToFaceColors( geometry );
geometry.computeMorphNormals();
// the old code to set color to the model
//var material = new THREE.MeshLambertMaterial( { color: 0xffffff, morphTargets: true, morphNormals: true, vertexColors: THREE.FaceColors, shading: THREE.SmoothShading } );
// my code
var meshAnim = new THREE.MorphAnimMesh( geometry, new THREE.MeshFaceMaterial( materials ) );
meshAnim.duration = 500;
meshAnim.scale.set( 20, 20, 20 );
meshAnim.position.y = 150;
meshAnim.position.x = -100;
scene1.add( meshAnim );
morphs.push( meshAnim );
} );
Except the documentation and some basic tutorials scattered across the web, is there anywhere i can learn three.js from ground up. like i know setting up scene and creating basic geometry stuffs but some detail info like loading textured model loading scenes etc.
I have created a series of commented examples for Three.js that illustrate features one at a time, starting with very basic features and progressing to more advanced ones (including loading models).
http://stemkoski.github.io/Three.js
Hope this helps!
Working with complex geometry, materials, textures, and animations are some of the hardest things to figure out in THREE.js - that's why we started there with our editor.
We make all of these easy. Export an FBX file (or OBJ/MTL, or Collada) from Blender. Bring it into a project in Verold Studio, then load it into your THREE.js program using our loader. Service is free for use, you pay us if you want enablement services or have a client who wants a maintenance/support agreement.
See the example below, couldn't be easier to bring your scene to THREE.js,
http://jsfiddle.net/rossmckegney/EeMCk/
// 1. Set and then start the animation :)
this.model.setAnimation("mixamo.com");
this.model.playAnimation(true);
//this.model.pauseAnimation();
// 2. Get the threedata for a model
console.log(this.model.threeData);
// 3. Move the model
this.tweenObjectTo(
this.model.threeData, // the model
new THREE.Vector3(1, 0, 0), // go to
new THREE.Quaternion(), // rotation
1, // time, in seconds
false, // smooth start
true); // smooth end
// 4. Clone the model
that = this;
this.model2 = this.model.clone({
success_hierarchy: function(clonedModel) {
that.veroldEngine.getActiveScene().addChildObject(clonedModel);
}
});

Categories