CeeJay Posted July 2, 2016 Share Posted July 2, 2016 Hi there I've spent a few hours trying to look into changing the uScale and vScale of the texture on an object-by-object and I'm totally stuck. To give you a simplified example of what I'm trying to do: Let's say I have lots of planes that are supposed to represent tiled walls. The planes are all different sizes and shapes, e.g. one might be 1×1, another 1×2, another 4×3, ... and so on. The same tiles are used on all of the walls, and I'd like to use the same repeating texture. The texture needs to have the same relative size everywhere it is used; e.g. it would look weird if the tiles on a 1×2 wall had the same height but were twice as wide as the tiles on a 1×2 wall. This means that I will need to use a different uScale and vScale on each plane. However I have the problem that the uScale and vScale are set on the texture, not the planes they are applied to - changing the scale for one changes the scale for all. After a few hours of Googling, as far as I can tell, if I want to achieve the effect I am going for I have three options, none of them very good: Build all of the bigger walls out of 1×1 walls. Create a different material and a different texture for each combination of uScale and vScale that I need in the scene. Write my own custom shader material that has the options to set uScale and vScale independently for each object. (1) and (2) are doable but I'd worry they're inefficient. (3) would be efficient but I'm struggling to make my own shader material that has all of the features of Babylon's default shader material, and work out how to pass custom variables to it. Googling has uncovered various forum posts and tutorials that cover some of the steps needed to do this, but I can't find all of the documentation I need for the whole process. After being stuck for a few hours I thought I really ought to ask here to see if anyone knows something obvious I'm missing! Thanks for your help! Quote Link to comment Share on other sites More sharing options...
Wingnut Posted July 3, 2016 Share Posted July 3, 2016 Hiya @CeeJay, welcome to the forum! What a great challenge, well-researched, and a well-presented post here. Nice job! Well, I guess there's a few who would have wanted to see a playground example of the issue, but not a big deal, here. You explained it perfectly. First, let's ping @NasimiAsl, the local God of Shaders... and see what he has to say. (he saw me use his name in this post, so we've rattled his cage) Yes, you want the tiling (all one texture) to be the same size-scale on ANY-sized wall, but the UV mapping on various sized walls... is stretching-to-fit... so big walls have bigger tile-squares, and little walls have little tile-squares (not-wanted). Perhaps... mesh.materialWrapPerMeshScale = true/false ? Or maybe mesh.allowMaterialScaling = false ? (neither exist, yet) These are strange ideas, because, in this case, we are allowing the mesh to "have a say" in how materials are applied to it. Interesting, perhaps not a good idea, and perhaps not possible. (I am pretty good at thinking-up poor/impossible solutions.) I'll keep thinking, but, you may be right... custom shader. I can't help much with that. Others are nearby, though. This seems to be a rather important issue for high-efficiency world-building. It is almost imperative that the same texture CAN be used on MANY wall sizes, and the tiles look the same, no matter the wall size. Something tells me we are missing something simple, here. I can't hardly believe that we have not encountered this challenge, earlier. Maybe it is only because I'm not into world-building very much. Quote Link to comment Share on other sites More sharing options...
jerome Posted July 3, 2016 Share Posted July 3, 2016 for now, the way to go would be to change (update) the mesh geometry about its UV parts (UVKind). When I get some time, I'll probably add this feature as a parameter on every CreateXXX() methods. Quote Link to comment Share on other sites More sharing options...
CeeJay Posted July 3, 2016 Author Share Posted July 3, 2016 Ah, okay, that's a lot better! So basically I've made this function: function setUVScale(mesh, uScale, vScale) { var i, UVs = mesh.getVerticesData(BABYLON.VertexBuffer.UVKind), len = UVs.length; if (uScale !== 1) { for (i = 0; i < len; i += 2) { UVs[i] *= uScale; } } if (vScale !== 1) { for (i = 1; i < len; i += 2) { UVs[i] *= vScale; } } mesh.setVerticesData(BABYLON.VertexBuffer.UVKind, UVs); } Calling it on each mesh seems to work as intended - can you think of any side-effects or am I golden? jerome and NasimiAsl 2 Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted July 4, 2016 Share Posted July 4, 2016 I think this is perfect. Excellent understanding of the inner working engine:) Quote Link to comment Share on other sites More sharing options...
NasimiAsl Posted July 4, 2016 Share Posted July 4, 2016 i really disagree about change uv in engine Buffer it is my personal advise because i think when we scale the uv we can not use correct texture we just use the Tiled texture. we can scale that in shader with best performance and very flexible * it used from shader Builder see this : http://www.babylonjs-playground.com/#1QQOJR#0 http://www.babylonjs-playground.com/#1QQOJR#1 notic : you most scale uv per texture more http://www.babylonjs-playground.com/#1QQOJR#2 how can you manage 2 or 3 texture in your floor or wall ? http://www.babylonjs-playground.com/#1QQOJR#3 http://www.babylonjs-playground.com/#1QQOJR#4 other way for make uv use planar Mapping http://www.babylonjs-playground.com/#2KMG5C#1 plan position.xy http://www.babylonjs-playground.com/#2KMG5C#2 plan position.zy jerome 1 Quote Link to comment Share on other sites More sharing options...
CeeJay Posted July 4, 2016 Author Share Posted July 4, 2016 Hi NasimiAsl, thanks for your reply! I'm still new at this, so I might not have understood them fully, but I did my best to read through some of the code examples you gave. I notice in your GLSL code, you have the uScale and VScale hard-coded rather than use variables. This was actually something I was stuck on when I was trying to get the shaders working. I know it's possible to pass in variables to avoid having to hard-code them. I've managed to do that a few years ago when I was playing around with THREE. I've yet to figure out how to do it in Babylon but give me some time, I've only just started using the framework ^_^;; However I think I am limited to two types of variable that I can pass in: Uniforms are set on a per-shader basis. If I make the uScale and VScale uniforms, then I'll need a new shader material for each object. Attributes are set on a per-vertex basis. If I make the uScale and VScale attributes, then I'll need to enter them in once for each vertex. I think I'm no better off than I was before, unless I've missed something like a per-object variable that I can pass to the shader. Quote Link to comment Share on other sites More sharing options...
dbawel Posted July 4, 2016 Share Posted July 4, 2016 @CeeJay - perhaps I don't understand correctly, but if I do, then you might want to consider testing using the x and y scale of the plane meshes to generate the results you desire, then apply those values to the U and V scale of the textures. This might provide you with the flexability you're looking for, and also other benefits you haven't yet discovered. Again, I hope I understand the questions, and hope perhaps this might be an alternative to altering the U and V scale of the textures in the variables so that you aren't required to dispose of these once you find the desired UV scale values - as memory may become a huge issue depending on your scene. Cheers, DB Quote Link to comment Share on other sites More sharing options...
CeeJay Posted July 5, 2016 Author Share Posted July 5, 2016 Ah yes sorry, I had worked that out earlier after the help above! I think that's the way to go and I've got past where I was stuck. Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted July 5, 2016 Share Posted July 5, 2016 Just a warning here: to set an UV scale per object through a specific shader, it will require writing a specific shader and thus you won't be able to use all the features provided for free by the StandardMaterial. To your point: Quote Uniforms are set on a per-shader basis. If I make the uScale and VScale uniforms, then I'll need a new shader material for each object. Nope they could be set on a per mesh basis as well.So this could work great in your case. Quote Link to comment Share on other sites More sharing options...
CeeJay Posted July 5, 2016 Author Share Posted July 5, 2016 34 minutes ago, Deltakosh said: Just a warning here: to set an UV scale per object through a specific shader, it will require writing a specific shader and thus you won't be able to use all the features provided for free by the StandardMaterial. I was looking through some of the source code and I found the code for the Pixel/Vertex shaders. Yeap there's a lot there! I was considering trying to copy it with some lines changed, but figured that was probably quite a complex thing to do... 34 minutes ago, Deltakosh said: Nope they could be set on a per mesh basis as well.So this could work great in your case. Arg, I'm sorry, I was looking but I couldn't find anything about that anywhere. I don't suppose you know where I might find some documentation or an example? Or failing that, a few variable names I should be looking for in the babylon.2.4.max.js source code? Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted July 5, 2016 Share Posted July 5, 2016 My hint is here: you should stick with the function you wrote: This works perfectly as long as you change it from time to time (not every frame I mean) Here is an example of mesh value updating the shader: https://github.com/BabylonJS/Babylon.js/blob/master/src/Materials/babylon.standardMaterial.ts#L520 (But I must admit this is not something I suggest. Shader should only be controlled by material for caching sake). Quote Link to comment Share on other sites More sharing options...
CeeJay Posted July 5, 2016 Author Share Posted July 5, 2016 Ok, I will do then, thank you very much! Quote Link to comment Share on other sites More sharing options...
Wingnut Posted July 6, 2016 Share Posted July 6, 2016 Hi again, guys. I'm not sure where everyone is going, here, but if your objective is to make MANY sizes of wall, and have the pattern look the same, no matter the size... ...then you COULD try a reflection texture in coordinatesMode = 4. http://www.babylonjs-playground.com/#1QQOJR#7 This SEEMED like a perfect solve... until I moved the camera around. Then, all hope for my idea... was lost. Wingnut - swing and a miss... strike 2. Speaking of 2, coordinatesMode = 2 is interesting, too. A little better than 4, but I don't know how it would look on room walls. Quote Link to comment Share on other sites More sharing options...
oschakravarthi Posted September 27, 2018 Share Posted September 27, 2018 Hi friends, I have been struggling to find a solution for the same problem. Can you please help me? Thanks in advance. Quote Link to comment Share on other sites More sharing options...
Guest Posted September 27, 2018 Share Posted September 27, 2018 can you describe what you need? A playground could help ":) Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.