HarbourMasters / HarbourMasters/Shipwright

Fixing the path issue for real

Open
#2,722 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
C
Stars
5.4k
Forks
837
Avg merge
1d 9h
Merged PRs (30d)
72

Description

originally posted by @Kenix3
```
My solution is potentially bad if the game draws decals and depth write stuff next to each other
That doesn't happen normally
But it's just flushing all the drawing whenever a decal is found and attaching the depth buffer as a pixel shader resource
Then running depth comparisons near N64 precision to check if it's "equal"
Since decals never need to write depth it works fairly well
If it goes back to something that needs depth writing then it detaches the buffer and uses it as normal again
I think that works in both gl and d3d11
Worth noting you still need the depth offset so it draws "on top" at least
And then you can just discard for pixels that the depth isn't "the same"
When brought down to N64 precision
And yeah they're mostly a side effect of the low depth buffer precision
They wouldn't work on other hardware with the same rules at all
```

```
Right now the cheapest approximation I could find so far:
- Rendering order stays the same as original.
- All decals that use ZMODE_DEC force all drawing to be flushed if it hasn't already. Since decals and transparent stuff are usually drawn by the game in the same layer, keeping track of whether anything that writes to the depth buffer in-between is a good way to skip useless flushes.
- Each time this flush is required, it should be possible to bind the existing depth buffer as a shader input in read only mode. If depth writing is required, it must be bound as read/write as it was before.
- Once you have it bound as read only, sampling the depth buffer with the shader is doable.
- Decals are only drawn if the current depth of the pixel you're about to draw (position.z) are within a certain margin of tolerance of the value in the depth buffer at that pixel.
- The margin of tolerance is the biggest absolute sum of each derivative of position.z across X and Y. So far from what I tried in D3D, (abs(ddx(pos.z)) + abs(ddy(pos.z))) * resolutionScaling (multiplier from 240p) is a pretty good estimate of the margin of tolerance.
- The actual rendering in stuff like ParaLLEL involves a lot more integer math and precision issues. You might need to cap the lower bound of this tolerance to a small value to always have a tolerance in case the derivatives are zero. I know how to compute this lower bound (ParaLLEL calls it "coplanar"), but it's probably not worth the effort of getting into N64-level depth encoding. Values between 0.0005 and 0.00001 across the 0 to 1 range as the lower bound of the tolerance will work decent enough.
- The real rendering also involves picking the biggest derivative either from the pixel being drawn or the one stored on the framebuffer already. Since this is far more expensive to emulate, and I honestly doubt there's many situations where the surface angle of the pixel is very different from what was drawn before, I think it can be ignored.
```

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.