Support for negative values in Pixel Depth Offset

The new Pixel Depth Offset value that materials can take is really nifty, but unfortunately it can only tell objects to render further BACK than they normally would.

I’d like a way to feed negative values into this parameter so that it can tell objects to render further FORWARD than they normally would.

In particular, this is useful for particle systems which use planar particles to represent volumetric objects. A particle will always render facing the camera but if it’s attached to, say, a hand socket, it will render THROUGH the hand. A negative Pixel Depth Offset value would allow me to force it to always render X units FORWARD, which would give it the appearance of always being in front of the position it actually exists. So a particle which is 25 units across could use a material with a -25 (or whatever the corresponding value is) pixel depth offset; this would make it appear to be a 25-unit sphere, since it would appear in front of objects within 25 units of it and always facing the camera.

I believe this “positive behavior” has to do with the deferred rendering path.
Don’t know if Epic is planning on improving it but, for now, you could use World Position Offset in your shader to move the particle vertices towards the camera.

If I understood the docs correctly, you can do it using CameraVectorWS, multiplying it by 25 and plugging it on the World Position Offset.
Or, you could normalize the result of CameraPositionWS - ParticlePositionWS, multiply it by 25 and plug that, instead.

Hi RhythmScript:

I experimented with this a week or so ago. You can enable negative values locally (at your own risk of course) by editing the file:

Engine/Shaders/MaterialTemplate.usf

and changing this line


       float PixelDepthOffset = max(GetMaterialPixelDepthOffset(MaterialParameters), 0);

To be:


       float PixelDepthOffset = GetMaterialPixelDepthOffset(MaterialParameters);

then re-make (I’m not entirely sure that step is needed, but I did it to be safe). After this, the next time you load a project all the cached shaders will be recompiled, and negative pixel depth offsets should work. That took me forever to find! It did the trick for me, though in the end pixel depth offset ended up not being what I wanted for other reasons.

Hope that helps.

I’m sure Epic had a reason for clamping it, so I think this falls under the category of “buyer assumes all responsibility” if you do it, BTW. For what it’s worth, I didn’t see any obvious problems for my use model. .

Edit I should also state: I did this for OpenGL. DX, I have no idea. I didn’t see any obvious sign that file was GL specific, so perhaps it’s translated per shading language somehow. Just something to be aware of, if it doesn’t immediately seem to work. I didn’t dig very deep once I figured out I didn’t want pixel offset after all.

I looked at MaterialTemplate.usf in UE 4.10 Preview1 and found they haven’t changed anything for this.
I also want to use negative Pixel Depth Offset value, which will be super useful especially for making cross section shader.

Sorry for the neco, but I thought it’s better than to make a new one. I’d be interested in this too, or more specifically, whether or not there’s a reason why it’s positive only. Are there any adverse effects to negative PDO?

There’s a Camera Offset Module in Cascade which is designed to draw the sprites as if they are closer to the camera without modifying their world position. That’s what you want to use

I don’t need this for particles, I need it for hair. I need to offset it much like they did in the Paragon hair, via a heightmap, but if I offset it “forward” it goes into the head. I’d rather offset if backward.

Pixel depth offset values can only be positive by design - there’s a very important GPU optimization that we can leverage by only pushing into the screen. It’s called ‘conservative depth writes’.

The short summary is that if you use conservative depth writes, the graphics card will still skip shading occluded pixels! This is really important for performance. If you do arbitrary depth writes, the graphics card can’t skip shading occluded pixels because your depth write might cause that pixel to be visible.

Usually what we do is use WorldPositionOffset to pull the geometry toward the camera, then use Pixel Depth Offset to push pixels away from the camera. In the kite demo we used this on trees - the billboard is halfway through the tree.

btw removing the Max will allow OpenGL to work, because it does not currently make use of conservative depth writes, only D3D11 and PS4 do. I would not expect negative values to work in D3D11 even if you remove that max. The max is just to make sure all platforms behave the same.

DanielW - Could you share some insight on how you guys solved the issue of pushing hair back in Paragon to avoid sharp plane intersections, but not having the hair push all the way into the head?

I don’t know that, maybe send Jordan a message on twitter? (lead artist on Paragon, who worked on the hair)
https://twitter.com/Mutantspoon

Thanks for the tip!