Applying shader material alters UV's

Hi guys, messed around with BJS couple of years ago and now I’m back to play with shaders :slight_smile:

Playground link: https://playground.babylonjs.com/#WCC3FG#11

So, I’m loading a model with material and mesh and looking to replace the existing material with a ShaderMaterial. As per the playground, when I do so seems to knacker up the mapping of UV’s to the model.

I’m guessing it’s a problem on the vertex/pixel shader side, but it’s not clear to me where it is - the shaders are based on the tutorials, and I had expected them to work out the box.

Edit: Links for shaders -
https://raw.githubusercontent.com/Pdh362/PublicAssets/master/testshader.fragment.fx
https://raw.githubusercontent.com/Pdh362/PublicAssets/master/testshader.vertex.fx

Suggestions? And apologies in advance if its something I should’ve seen!

Hi Pdh362,

WARNING: This reply got a lot more involved than I expected it to as half-way through my response a network issue resolved itself, so I was able to dig into the problem more deeply. :slight_smile: Sorry about the length.

First of all, welcome back to Babylon! Your Playground is currently not working for me, even though it was a second ago (I’m guessing something happened with the external resources), but I did notice a few things that might be causing it to behave strangely.

In your Playground, you actually declare a new canvas variable and instantiate a new Babylon.js engine on lines 2 and 3, respectively. The Playground actually already provides those variables for you as an existing part of the scope: see the default playground for an example where it uses engine and canvas without having declared or initialized them at any point. It’s a little magical; but generally speaking, when using the Playground, you want to use a createScene() function as your entry point, then use the provided canvas and engine variables. You also don’t need to run your own render loop, as that’s done automatically for the provided engine.

To be clear, I’m not sure that’s what causing the UV problem, but it’s definitely adding some weirdness that makes the problem harder to diagnose. WebGL preserves state, and Babylon.JS Engines operate under the assumption that no other objects are messing with that state, so having two Babylon.JS engines running in the same context could definitely cause unexpected behavior. Since I started writing this, your Playground has started working again, indicating the problem was almost certainly network issues; I modified it a bit to make it easier to debug: https://playground.babylonjs.com/#WCC3FG#12.

That done, I was able to debug the scene using Spector.js, which is a magnificent tool if you need to debug web shaders. One of the coolest features is live editing, which allows you to change a shader on-the-fly and see the results rendered in the original window. Using that, I was able to debug the shader and get the correct output by doing this.

image

So, I think the issue is that your UVs expect your texture to be Y-flipped relative to how the texture comes in. Depending on how you plan to use the shader/textures, there are several tacks you could take to solving that problem, the most flexible of which might be to modify the shader to allow you to flip the Y at compile time, should you so desire.

#ifdef UV_INVERT_Y
vUV = vec2(uv.x, 1.0 - uv.y);
#else
vUV = uv;
#endif

I seem to remember there being a standard way to do that, like an option on the sampler or something, but a quick search isn’t turning up anything. Hopefully it won’t be too invasive a fix any way you tackle it, though.

1 Like

Epic response, syntheticmagus - and that did fix the problem. I knew the playground was a little ‘clunky’ when I threw it together, so thanks for the advice. Great advice about spector.js as well - I’ll be spending next week playing around with that one!

Now to have a word with the artists about why their UV’s seem to be mapped upside down :roll_eyes:

1 Like