thinInstance multiple materials

Thanks @kvasss that’s actually I am not understanding on which elements I have to loop, could you please provide an example with my code above?

Loop for 64x64

for (i = 0; i < 64; i++) {
// Set rows here… vOffset?
for(j =0; j < 64; j++) {
Set columns here… uOffset?
}
}

It doesn’t still clears me, see in my code I am creating multiple instance, so I have a new variable newStand which holds the instance, so on what I need to set offset?

for example newStand.vOffset ?

so each stand has a unique offset in my loop above

I think what @Deltakosh wanted to say is that you would have to use a custom instance attribute given you the offset (x,y) in the atlas to use for mapping. That would also mean you need to use a custom material / shader to read this offset and apply to the texture coordinates before reading inside the atlas.

See this section for custom instance attributes: Use Instances - Babylon.js Documentation

1 Like

Thank you @Evgeni_Popov for those directions, I was able to follow and apply different colours on each instance, here is a PG https://www.babylonjs-playground.com/#YAWQ2W#15

but for material I am still struggling for custom material, I have read Introduction to Shaders - Babylon.js Documentation but still not very clear on how I will load my material image there, a PG will really help me understand all this. I think I maybe I could use https://cyos.babylonjs.com, but I don’t understand on how to set UV’s for material. I have included a material image, which I want to display different part/UV on next stand https://www.babylonjs-playground.com/#YAWQ2W#16

You can try something like this:

https://www.babylonjs-playground.com/#YAWQ2W#18

Notes:

  • you should make all your tiles the same dimension in the texture. It’s currently not the case. I used a tile dimension of 68x75 but given the texture it’s not totally accurate
  • this works by passing to the shaders the (x,y) offset of the tile in the atlas you want to draw for the current instance. In addition to (x,y) I pass the (width, height) dimensions of the tile. You could avoid this because your tiles have a fixed size, but it’s more general that way, you could use tiles with different dimensions with this code
  • to work correctly, you need that your panel have texture coordinates that encompasses the full (0,0) - (1,1) range. Currently it’s not the case, that’s why the letter appears truncated and too big.
  • I did fx = 1. - fx because else your letter appears reversed. You can avoid this line by fixing your texture coordinates directly in the model
  • you should add some padding around your tiles in the texture (and update accordingly the ofst value in the code), else you can get artifacts because of mip mapping. It’s a known problem when using atlas, see for eg Texture Atlas edge artifacts...how to fix? - OpenGL: Advanced Coding - Khronos Forums
1 Like

You will see a problem in the previous PG, which is that tile + color displayed on a panel changes when you move!

That’s because the instances are culled, and when not visible they are not drawn. However, as we provide a full buffer for colors and tileOffsets and this buffer does not change from frame to frame, when one instance is not displayed anymore, another instance gets the parameters of this instance. For eg, if instance 0 that uses values from colors[0] and tileOffsets[0] is not visible anymore, it’s instance 1 that now uses colors[0] and tileOffsets[0] for its display.

To correct this problem you should use the 2nd possibility described in Use Instances - Babylon.js Documentation to set the instance attributes. Namely, you should set the attribute values on each instance directly:

https://www.babylonjs-playground.com/#YAWQ2W#19

1 Like

:bow: I am going through all your points and clearing my doubts, I will create a PG with 2nd alternative method as you mentioned, meanwhile I noticed this doesn’t display texture in Safari (Version 13.1.2 (14609.3.5.1.5)) but it display texture in Chrome,

:bow: ah just noticed you had a pg already with registerInstancedBuffer

Safari is WebGL1.

I think the problem is that the texture is redimensionned as it is not a power of 2 texture. You should replace the 1083 and 1200 constants in my code to values retrieved from the texture (myMaterial.diffuseTexture.getSize()). Make sure however that the texture is loaded before doing this, else you will get 0 results.

1 Like

can this be done in BJS or I have to update mesh in 3d software?

ok thanks, still reading on this.

I created a new texture with dimension 340X375, it has 25 tiles, each 68X75
so when I am in Chrome myMaterial.diffuseTexture.getSize() returns me {W: 340, H: 375} which is already set in code, but in Safari myMaterial.diffuseTexture.getSize() returns different {W: 256, H: 256} here is PG https://www.babylonjs-playground.com/#YAWQ2W#23

Power of 2 you mean double sized texture? so I increased sizeX2 , and here texture is 680X700 , but Safari gives different result myMaterial.diffuseTexture.getSize() {W: 512, H: 512} and still not able to show texture
here is PG with it https://www.babylonjs-playground.com/#YAWQ2W#24

can this be done in BJS or I have to update mesh in 3d software?

Yes, but you would need to locate in your mesh the vertices corresponding to where the texture is applied and update the uv coordinates. If you can use a 3D software I think it would be a lot easier.

Power of 2 you mean double sized texture?

No, in WebGL1 all textures must have a power of 2 width and height so Babylon will rescale your texture so that it is a power of 2 texture. That’s why 340x375 becomes 256x256.

The problem is that now your tiles are not 68x75 anymore but 68 * 256/340 and 75 * 256/375…

If you want it to work with WebGL1 it would be a lot easier that your texture is a power of 2 right from the beginning, that way you would not need to perform those corrections.

1 Like

Also, you need to use texture2D() and not texture() in the fragment shader so that it works in WebGL1:

https://www.babylonjs-playground.com/#YAWQ2W#27

1 Like

for this I ask my 3d guy and he doesn’t get what is encompasses the full (0,0) - (1,1) range , I am attaching a UV he just sent for the stand he has

ok I created a new texture 256X256 dimension, it has 9 tiles, 80X80 and between them is 10px space, what should be value of ofset? and how can I keep one tile to each stand, right now its showing randomly on refresh page.

Regarding the uvs, the panel on which the texture will be applied should have a (0,0) texture coordinate for the top left corner and (1,1) for the bottom right corner (and the right coordinates for all the other vertices making of the panel). That way, when the texture is applied on the panel, u is going from 0 to 1 and v is going from 0 to 1 too.

Regarding your picture it won’t work: you need that each tile be exactly the same size. The 1 and 2, for eg, have not the same size because 1 has no top/left borders.

For eg, if you make a 4x4 tiled atlas in a 256x256 texture, each tile will be 64x64. Then, in each of these 64x64 blocks, you can make a border of 5 pixels on each side (top/right/bottom/left), leaving you 54x54 pixels usable for your number/character. The border should be the same color than the background of the tile.

In the code, set ofst = size of border (5 in the example above).

1 Like

Ok I received updated model and a new uv image to use with 512X512 dimensions. I updated PG https://www.babylonjs-playground.com/#YAWQ2W#32

why is it too much zoom? is it model or the code?

is it possible to create UV’s with code please? cause the guy helping me for model also is out of idea now about this.

edit 1: and here is with 256X256 texture which is showing correct colours but same zoom issue
https://www.babylonjs-playground.com/#YAWQ2W#39

edit 2: if I scale texture I am able to see something

myMaterial.diffuseTexture.uScale = 11;
myMaterial.diffuseTexture.vScale = 6;

https://www.babylonjs-playground.com/#YAWQ2W#40

so definitely scaling issue.

The problem is the uvs of the panel.

Here’s a corrected PG:

https://www.babylonjs-playground.com/#YAWQ2W#41

1 Like

:bow: was it code related or some issue with model, if model, what must needed to be done to fix uvs of panel in 3ds?

It would be better to have this fixed in 3ds, that would avoid the custom code to set the right uvs.

I don’t know 3ds, however, so I can’t explain what to do. Maybe @PatrickRyan will know?

1 Like

Thank you so much @Evgeni_Popov I learned a lot from this and wouldn’t have reach here without you.

I was also thinking if its possible to download fixed stand object and than replace my model with this fixed one, it will load without custom code, I found Save Your Scene - Babylon.js Documentation , but I see couple of issues here.

  1. It save as .babylon file, is their something to save it as .obj?
  2. as you see I have like 36 meshes in task.loadedMeshes, but the doDownload function provided in above link download single mesh, to fix I was thinking to maybe create a new TransformNode or object and all meshes as children of it, and than download parent mesh. or is there any better way?

not sure it fits your needs, but the SPS may be sometimes an option
https://doc.babylonjs.com/how_to/solid_particles#different-materials

1 Like