Jump to content

Best way to create multiple textures, based on a single svg


sallf
 Share

Recommended Posts

I'm trying to create multiple textures, with different resourceOptions, based on a single svg. Here's what I've tried so far:

 

1. Using `fromUrl` (& `from`)

  const texture1 = PIXI.Texture.fromURL('./some.svg', {
      resourceOptions: {
        width: 10,
        height: 10,
      },
    });

    const texture2 = PIXI.Texture.fromURL('./some.svg', {
      resourceOptions: {
        width: 100,
        height: 100,
      },
    });

In this case, texture2 just returns the texture1 from TextureCache.

 

2. Using the loader

let resources;

loader
  .add('texture1', './some.svg', {
    metadata: {
      resourceOptions: {
        width: 10,
        height: 10,
      },
    },
  })
  .add('texture2', './some.svg', {
    metadata: {
      resourceOptions: {
        width: 100,
        height: 100,
      },
    },
  })
  .load((_, resources) => {
    resources = resources;
  });

This works but gives the warnings "BaseTexture added to the cache with an id that already had an entry" and "Texture added to the cache with an id that already had an entry". This also adds 3 entities to the TextureCache: `http:.../some.svg`, `texture1` and `texture2` which seems strange. Should I just ignore this warning, or is there a way to provide a unique id?

 

Ultimately, what I want to be able to do is cache an svg file from the server, create a single texture from it (so I can grab the original width/height of the svg - so I know the aspect ratio), and use that to create multiple textures that are proportionally sized, as the app determines they are needed. Maybe there's another way to approach this? Any help appreciated!

Link to comment
Share on other sites

pixi "texture cache" is an easy things - it adds texture to the map. Just look where its done in source code. There's no docs, no articles, ande every time someone stumbles across it the answer is only one - look in the source code.

I usually dont use cache at all and empty it every time with "utils.clearTextureCache" and basetexturecache too. This thing is not needed.

As for multiple levels - you can try upload those to different mip levels in webgl texture, in that case you can make Texture Resource (look example with gradient, but add bot texImage2d's on different levels).

You can also do it manually, just specify different resolutions (i mean dpr) in baseTexture, again, no articles or demos, you have to be the one who'll make it and share with other people :) previous guys failed to do that. Usually resolution goes 1,2,4,8, e.t.c. by powers of 2. 

Link to comment
Share on other sites

@ivan.popelyshevthanks for sharing some thoughts!

 

I had seen a few instances where people used url params to beat Pixi returning a cached version, and I think was talking more about "network" caching. The below code works fine, but I think it makes 2 requests to the server for the same asset. Obviously this is not Pixi related, except that I might have expected to be able to pass an `id` or other argument to return a different texture from the same URL.

 

const texture1 = PIXI.Texture.fromURL('./some.svg?width=10&height=10', {
  resourceOptions: {
    width: 10,
    height: 10,
  },
});

const texture2 = PIXI.Texture.fromURL('./some.svg?width=100&height=100', {
  resourceOptions: {
    width: 100,
    height: 100,
  },
});

 

I believe this is the gradient example you referenced? Mipmaps were an interesting suggestion, but after exploring it for a while, I think I'm looking more for 'on demand' sizing as opposed to 'responsive'... Though, maybe they are the same thing and I just couldn't figure out how to do that with BaseTextures.

 

Ultimately what seems to be working best for me is creating an `SVGResource` and using its `load` method to get the resource and create a texture out of it. I'm building in react, so I implemented it as this hook below. You mentioned that you usually clear the texture cache every time, so I'm doing the same :).

 

export const useSvgTexture = (url, width = null, height = null) => {
  const [texture, setTexture] = useState(null);

  useMountEffect(() => {
    const params = {};
    // Typically it's best to pass only width or height and the resource
    // will scale proportionally
    if (width) params.width = width;
    if (height) params.height = height;

    const resource = new PIXI.SVGResource(
      url,
      params,
    );

    resource.load().then((res) => {
      const txt = PIXI.Texture.from(res);
      PIXI.utils.clearTextureCache();
      setTexture(txt);
    });
  });
  return texture;
};

 

I need to close some open tabs, so here are some related discussions for anyone else looking for related help ... most of which are Ivan providing the best answers :)

Scaling SVG before rasterizing

Mazilla WebGL best practices - Mipmaps

Learning Pixi - A little more about loading things

Pixi - Manually setting texture mipmap levels

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...