Triplanar Texture Mapping Code

Last year I had to do some triplanar texture mapping for a project. For that I had to go off of Unity guides on how to accomplish it. I finally got around to putting together a PlayCanvas demo project of that functionality for anyone looking to do that kind of thing.

Demo project: PlayCanvas | HTML5 Game Engine
Demo preview: [WIP] Tri-Planar Tex Projection - PLAYCANVAS

Screenshot:
image

Use-cases

  • In my case I had a model that would morph in size, it was important that textures did not stretch across the model. While adjusting the “tiling” on the material was an option, tweaking the tiling numbers at the same time the model morphed, proved to be very finicky. Which is why triplanar texture mapping was chosen since that is a non-issue.
  • A very popular use-case is for terrain. You can have the walls of a canyon be a cliffy/rocky texture that blends perfectly into a sandy texture on the non-cliff parts. An example of that is below: image

To accomplish the canyon-like trick, you’ll need to use different textures for the Y and XZ axis. This demo project doesn’t use different textures for different XYZ axis. But, that can probably be added without too much additional work.

Downsides

  • Cannot use UV mapping.
  • Since this approach uses 3 texture lookups instead of just 1, this operation is a little more expensive.

Additional Reading

Here’s a Unity tutorial that explains it pretty well (the terrain screenshot comes from it): Martin Palko - Triplanar Mapping

Leonidas has a great tutorial about using shader chunks and masking with shaders: Texture masks using a shader | Playing in Canvas

5 Likes

Nice! Thanks for sharing this @Chris, it can quite useful in lot’s of projects.

1 Like

That works really well, nicely done!

1 Like

Hi @Chris

I know it’s been a while, but I’m trying to add texture rotation to this shader and was wondering if you could point me in the right direction

Sorry, I haven’t been in the WebGL world for a couple years now. I’m not sure I can help with that specific change.

I recommend checking out the PlayCanvas docs and tutorials on Shader Chunks if you haven’t, since they’re one of the more confusing parts of WebGL. It looks like PlayCanvas has been revamping their shader chunk system, so my code might be out of date.

Texture rotation in a shader isn’t unique to this “triplanar” use-case, so you can try looking around online (webgl, Unity, etc) or asking on this PlayCanvas forum about that part in particular.

If you haven’t checked out Leonidas’s tutorial on shaders, I highly recommend it since it’s perfect for getting an overall understanding of shaders in PlayCanvas. Or if @Leonidas is not too busy making PlayCanvas look like Unreal 5, he might be able to help here too.

Also - this might sound crazy, but because you’re trying to change your own shader code in a very specific way. Asking ChatGPT to make that modification, might not be a bad idea. For example, I pasted some of the diffuse chunk code into ChatGPT and asked for a 90 degree rotation on the z-axis, and it seemed to give me good code.

cz = gammaCorrectInput(addAlbedoDetail(texture2D(diffuseTex, vec2(px + texPosx, -py - texPosy) / texSizez).rgb));

2 Likes