0
$\begingroup$

I have added a brief addendum to the end.

I have been getting into procedural vector displacement with shader nodes in Cycles. The other day I created a model and tried to animate it rotating through space (not using any vector transformations in the shader itself) only to find that it messed with the texture coordinates I was using. This is odd to me since I was using generated coordinates transformed to match object coordinates. I figured the generated coordinates were in local space and should allow me to rotate the source mesh however I want, applying that transformation to the displacement. Well, for some reason the global transformation changed the shape of the local displacement and distorted the object.

After trying a few things like using object coordinates and not finding any change to the results whatsoever, I did some research and found absolutely nothing relating to this issue at all. I thought that maybe I had just messed up my math and was referencing global coordinates somewhere and I just happened to make that mistake in all three of my experimenting projects. To be sure, I copied CGMatter's asteroid tutorial exactly as he had done it in as close to the same build of Blender as I could. Same problem. The product looked good, but simply rotating the model upside down turned it back into the shape of the source mesh (The project starts with a subdivided cube and ends with a very different-looking asteroid).

Next, I tried completely reinstalling Blender. This was after updating a few days before, so I wanted to really make sure nothing was broken on my end. That didn't work either. This means it's either a bug or I'm dumb, at this point. I don't have the confidence to say it's a bug, so I would appreciate it if someone could look over a quick project I created with the same problem and educate me in the ways of the Texture Coordinate node. If I did correctly interpret its function, and this is a bug, I will actually submit a report.

In this project, I'm doing the old cube-squeezed-into-a-pyramid displacement. If the source mesh is rotated about X or Y, it seems to invert some or all of the local coordinates (if the object is upside down, yes it should invert observed coordinates, but local should not change!). If the source is rotated about Z, the base rotates in the opposite direction from the top. The strangest part to me is that if you look at the coordinates being used by applying them to the output of the shader, they are mapped correctly, but the math being done appears not to be using this transformation in the same way.

Here is an image of the node setup: enter image description here

Again, I could be missing something obvious, but I feel like this should work in local object space no matter the orientation of the source mesh since the transformation to local space will always give back the same position vectors. The top of the cube should always be squished even if it's facing downwards because it's always locally the top.

Anyways, sorry for the VERY long post, I just have no clue what is going on and wanted to add as much context as possible. Here is a brief video of me messing with the object and the exact project file from the video:

YouTube Video

Download Project

One last time, thank you to anyone who made it through this!

QUICK ADDENDUM: So I wasn't very clear about which part of this is the problem. It's not how I have to cycle through render modes in the editor to get things to update to a global transform. I wouldn't have any problems at all, but when I go to do the final render, it updates every frame and turns the local displacement into the weird half local-half global displacement. My first inclination is that there is a bug in the way Blender is handling the vector displacement.

$\endgroup$
1
$\begingroup$

As always, open to correction, but reverse-engineering from the symptoms alone, this seems to be a caching problem.

  • If you plug the displacement vector straight into the Displacement input of a Material Output node, the vector seems to be evaluated in World space.
  • If you request a displacement in World space (however it is calculated,) you would expect an object to 'swim' through that displacement when it is rotated: in the viewport, it does not. The displacement appears to be cached in Object space. When the object is transformed, the displacement follows.
  • You can update the cache in at least two ways I've found.. flip out of Rendered to Solid mode and back again, or put a Vector Displacement node between the requested vector and the Material Output, and switch its space from, say, 'World' to 'Object' and back again.

The cache appears only to apply in the viewport: in frames rendered through a camera the displacement is updated correctly.

I think this may qualify as a bug..or it may considered a valid optimisation for viewport performance?

TL;DR

To evaluate the displacement vector in Object space, (so it follows the object, and therefore persists through flipping between Rendered and Solid modes), put it through a Vector Displacement node, set to 'Object Space'.

$\endgroup$
4
  • $\begingroup$ My problem isn't so much with when it's updated, but rather that it updates in global space at all. I'm trying to use the local object or generated coordinates which, I think, should only transform the mesh relative to its local space, in which case it should not swim at all. The fact that it transforms as expected before cycling out of and back into render mode is fine, but when I go to do the final render, it takes the messed-up global version and not the local version. I'm not sure if that's any clearer. I would guess it's a bug in the way the displacement is calculated. $\endgroup$ – BeginOblivion Nov 28 '20 at 13:36
  • 1
    $\begingroup$ @BeginOblivion I can't reproduce any unexpected behaviour, if, as in the last paragraph of this answer, the vector is put through a Vector Displacement node, set to 'Object Space'. If it's plugged straight in, as in your file, it's evaluated in World space, so you would expect it to swim. What's surprising is that it doesn't, in the viewport. The vector is calculated in Object space: to work as expected, it should be expressed in Object space. No bug in calculation. $\endgroup$ – Robin Betts Nov 28 '20 at 13:44
  • $\begingroup$ Unfortunately, the vector displacement node did not fix the issue. The problem is not with swimming coordinates, but with physical distortion in space when rotating. The local transformation is already converted into absolute position vectors by nature of the linear algebra happening in my node tree. I'm taking the object space and applying a transformation to it that converts it to "pyramid" space or "asteroid" space. I did stumble across a solution by constraining all rotation and driving a vector rotate node with the rotation transform of the source mesh. Thank you for putting time in here $\endgroup$ – BeginOblivion Nov 28 '20 at 15:32
  • $\begingroup$ Ahh.. OK.. Is the problem executing rotations in displacement? ..... Erindale is good on this.. $\endgroup$ – Robin Betts Nov 28 '20 at 15:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.