I’m trying to make per-object camera facing UV’s that “stick to” object for NPR textures (watercolor paper, sketchmaps, etc).
I figured the best way to do that would be to transform both the objects position and its vertices into either clip space or screenspace, then subtract one from the other and use the XY results as UV coordinates.
This kind of works when I try it in clip space, but I’m getting skewing at the edges of the frame and nasty, inverting artifacts when faces are perpendicular to the camera, and the texture isn’t perfectly screen aligned.
Clearly I’m missing something - some transform or scaling factor- anybody have any suggestions?
Also, I forgot that Kyle’s shader doesn’t use triplanar mapping, so it’s even easier to implement. I had done triplanar for one of my tests and actually abandoned it in favor of a 3d texture for the effect I wanted…
The stretching you see in the above image is from view space being an orthographic projection. When moving the positions around subtracting the pivot will indeed keep the view space UVs stable, but the stretching across the side is unavoidable.
Using clip space accounts for perspective and will prevent stretching, but you cannot prevent the “swimming” since the projection changes as the object moves.
In short it’s impossible to have a single view based projection that both prevents stretching and swimming. If you really were firm on keeping both you would have to pick one projection (probably clip space) and apply it as “static” UVs (or a constant matrix from script) so it can be reused for several frames and then swap or blend to a new one when it gets too far. Would work for rotation then too.
But honestly the constant scale technique is a lot easier and going to be a lot nicer looking.
I had try to implement this technique already in the past, I have zero mastery of projection, but didn’t unity provide a keyword like screenUV, I remember using that in early test (strumpy node). Why not offset base on that and ditch complex projection?
The second test I did was simply UVing the character in 0-1 projected space, which works well with rotation along the axis of projection, but of course you would have problem on rotation. In fact I was thinking of projecting an UV gradient and use that as a sampling for screen space texture … I have been wondering if I could use hybrid with a triplanar masking.
I don’t plan to try anytime soon though, I have other task to complete.
I couldn’t find my original example shader from that twitter post, so this is a little different in implementation. That original twitter thread I was using a constant scaling technique I wrote, and in this one I’m using the method from the Hashed Alpha Testing link I posted above. For Dino Frontier I ended up using something more like this, but I think my original implementation looks a little better for this use case.
Anyway, I’d go grab the example project from Kyle’s tutorial page and try using this shader in the demo scene.
I am currently trying to sample a texture in screen space and it works well. But I would like to be able to constrain uv position and scale based on object’s position and distance from camera. I found this post and other examples but I also faced some issues and for the moment I don’t see how to fix them.
I’ve been trying to make sense of how the camera facing uvs are calculated in that very sample but for the life of me I don’t understand how.
I’m very new to shaders and have a library of sub graphs i’m using as reusable functions in shader graph and so I’m trying to create that pencil effect in shader graph.
I can make it work as an object shader and can get this effect in a custom blit render feature:
So the last piece of the puzzle for me is to figure out the camera facing uvs in shader graph but I’m having a really hard time understanding what’s happening. How are the UVs being sampled in the replacement shader and how can I do the same with shader graph?
Because it doesn’t use camera facing UVs. It uses the mesh’s default UVs. My alternative shader scales the UVs so the texture is roughly constantly sized in screen space. But it’s still using the mesh UVs. The whole thing with that example shader was to show you didn’t necessarily need screen space UVs.
Now, for Shader Graph, if you do just want screen space UVs, you can use the screen position node.