New shader: cinematic depth of field
- OtisInf
- Topic Author
See PR: github.com/crosire/reshade-shaders/pull/90
Features:
- Near plane bleed into focus plane
- Advanced focusing helpers with hyperfocal near/far/focus planes blended using colors chosen by the user
- Fine-grained control over blur in near and far plane as well as blur quality and amount of near-plane bleed
- Auto focus and manual focus, where auto-focus can be driven by the mouse.
- Focusing based on real camera aspects like focal length (1-300mm) and f-number (1-22)
- Highlight extrapolation
- Resolution stable
- Circular bokeh only.
Focusing was one of the main goals of the shader, and I hope I've succeeded in that. It offers stable focusing, so it doesn't move the focusing point/depth when blur aspects are changed for instance. It also gives insights in what's in focus using a handy overlay (optional) and the camera aspects (focal length and f-number) offer simple tools to get things focused up quickly.
Seeing Unreal Engine 4.20 offering a 'cinematic depth of field shader' I worked towards the same quality and I hope I have come close. The near-plane bleed is something I'm happy with but might need some extra work, as well as the post-blur smoothing, which might not be as powerful as one might hope.
Focusing overlay:
Near plane bleed into focus plane:
Highlight extrapolation:
I'm not a shader expert, so I might have made mistakes or have done things less ideal, if so please let me know. Also if things don't work, please let me know as well so I can update the shader. Performance is on par with qUINT ADOF, often faster (9 passes, 6 rings).
I've cited all papers / presentations I've used in the sourcecode as well as added a lot of comments to help people who want to learn more about how it works.
Enjoy!
Version history:
- 21-sep-2018: v1.0.7: Better near-plane bleed. Optimized near plane CoC storage so less reads are needed. Corrected post-blur bleed. Corrected near plane highlight bleed. Overall micro-optimizations.
- 04-sep-2018: v1.0.6: Small fix for DX9 and autofocus.
- 17-aug-2018: v1.0.5: Much better highlighting, higher range for manual focus
- 12-aug-2018: v1.0.4: Finetuned the workaround for d3d9 to only affect reshade 3.4 or lower. Finetuned the near highlight extrapolation a bit. Removed highlight threshold as it ruined the blur
- 10-aug-2018: v1.0.3: Daodan's crosshair code added.
- 09-aug-2018: v1.0.2: Added workaround for d3d9 glitch in reshade 3.4.
- 08-aug-2018: v1.0.1: namespace addition for samplers/textures.
- 08-aug-2018: v1.0.0: beta. Feature complete.
Please Log in or Create an account to join the conversation.
- Daodan
With the focal length and aperture it is very intuitive to set up.
One thing though: the 'Highlight Gain' gives unexpected results.
First image is without, second with highlight gain (bright bands in the face, shirt/lower neck)
Please Log in or Create an account to join the conversation.
- OtisInf
- Topic Author
the highlight gain is more for creating these large circles of in the bokeh when blur is high. Thing is that if you have low blur like you have in your shots, you won't get big highlight circles like in my screenshot above, as the bokeh (blur) circles are small. Extend the blur a lot and you'll see them.
There appears to be a nameclash on the sampler definitions for some people, I'm looking into this (so the shader won't compile and give an error about a redefinition).
Nameclash doesn't happen with vanilla set of reshade shaders but I have added a namespace to the code for the people who do run into a nameclash.
Please Log in or Create an account to join the conversation.
- Marty McFly
20:44:33:352 [02404] | ERROR | Failed to compile '\ReShade\qUINT\TestDOF.fx':
\Spiele\Mods\ReShade Test\Shader@0x1E0A6620(18,11-42): error X3003: redefinition of '__SamplerU__ReShade__DepthBuffer'
\ReShade\qUINT\TestDOF.fx(550, 13): error: internal shader compilation failed
\Spiele\Mods\ReShade Test\Shader@0x11DA2F00(18,11-42): error X3003: redefinition of '__SamplerU__ReShade__DepthBuffer'
\ReShade\qUINT\TestDOF.fx(599, 6): error: internal shader compilation failed
\Spiele\Mods\ReShade Test\Shader@0x1E0A6620(20,11-42): error X3003: redefinition of '__SamplerU__ReShade__DepthBuffer'
\ReShade\qUINT\TestDOF.fx(550, 13): error: internal shader compilation failed
\Spiele\Mods\ReShade Test\Shader@0x1DD7B020(20,11-42): error X3003: redefinition of '__SamplerU__ReShade__DepthBuffer'
\ReShade\qUINT\TestDOF.fx(669, 6): error: internal shader compilation failed
Please Log in or Create an account to join the conversation.
- OtisInf
- Topic Author
It's indeed odd, someone else also had a problem but I couldn't reproduce it on dx11 with all the shaders, however I didn't include a namespace for the samplers/textures, so to be safe I now have added a namespace around the shader code to be safe (available in the PR now)Marty McFly wrote: Doesn't compile for me on d3d9, and I must say I don't understand the compiler errors
20:44:33:352 [02404] | ERROR | Failed to compile '\ReShade\qUINT\TestDOF.fx':
\Spiele\Mods\ReShade Test\Shader@0x1E0A6620(18,11-42): error X3003: redefinition of '__SamplerU__ReShade__DepthBuffer'
\ReShade\qUINT\TestDOF.fx(550, 13): error: internal shader compilation failed
\Spiele\Mods\ReShade Test\Shader@0x11DA2F00(18,11-42): error X3003: redefinition of '__SamplerU__ReShade__DepthBuffer'
\ReShade\qUINT\TestDOF.fx(599, 6): error: internal shader compilation failed
\Spiele\Mods\ReShade Test\Shader@0x1E0A6620(20,11-42): error X3003: redefinition of '__SamplerU__ReShade__DepthBuffer'
\ReShade\qUINT\TestDOF.fx(550, 13): error: internal shader compilation failed
\Spiele\Mods\ReShade Test\Shader@0x1DD7B020(20,11-42): error X3003: redefinition of '__SamplerU__ReShade__DepthBuffer'
\ReShade\qUINT\TestDOF.fx(669, 6): error: internal shader compilation failed
I only use this FX and the ReShade.fxh, and I don't see anything declared twice
(edit) your errors are indeed the same as the one reported on the PR ( github.com/crosire/reshade-shaders/pull/...suecomment-411493065 ), I didn't notice that. I don't have a D3d9 game lying around atm (have to download one) so can't test if the namespace wrap solves it...
(edit) downloading darksiders from steam now to see if it gives the errors (should be d3d9c)
Please Log in or Create an account to join the conversation.
- Marty McFly
Please Log in or Create an account to join the conversation.
- OtisInf
- Topic Author
That sucks of course, as I precisely moved these reads to the vertex shader to avoid a lot of fetches per pixel...
tbh I don't really care about d3d9 but I understand it has to work for d3d9 to be included... using a conditional compilation directive might work perhaps but that would of course create a mess with the code so I don't really want to do that. It works fine on dx11.
Please Log in or Create an account to join the conversation.
- crosire
Please Log in or Create an account to join the conversation.
- Marty McFly
Please Log in or Create an account to join the conversation.
- OtisInf
- Topic Author
Cool, makes sense indeed! I'll change that An alternative would have been a function filling the struct and a conditional compile to use the function directly in the pixel shader on d3d9, but this is easiercrosire wrote: Textures in vertex shader should work fine, but you can't use interpolation intrinsics there (since that isn't done until the fragment phase). So "tex2D" doesn't work. But "tex2Dlod" and "tex2Dfetch" does.
Please Log in or Create an account to join the conversation.
- Daodan
But GetLinearizedDepth() already uses "tex2Dlod". And changing that to "tex2Dfetch" also doesn't do any good.
I don't get it. Am I missing Something?
Please Log in or Create an account to join the conversation.
- OtisInf
- Topic Author
You beat me to it! I am looking again where I am using tex2D in the vertex shader but I don't do that. Marty's conclusion that that was the reason things failed isn't correct, I only use 1 call to a texture read, the linearized depth call, which indeed already uses tex2Dlod, the rest is merely calculations.Daodan wrote: So, the thing that makes the D3D9 compilation fail is the call of ReShade::GetLinearizedDepth() in the vertex shader because that function reads from the depth texture?
But GetLinearizedDepth() already uses "tex2Dlod". And changing that to "tex2Dfetch" also doesn't do any good.
I don't get it. Am I missing Something?
the errors themselves don't make sense either, like something messes up the generated hlsl with this input. Will see if I can dump out the hlsl generated by reshade to see what's wrong...
Please Log in or Create an account to join the conversation.
- crosire
Please Log in or Create an account to join the conversation.
- OtisInf
- Topic Author
Top is the crude output of a dump of the source to compile with the d3d shader compiler to a file WITHOUT a call to GetLinearizedDepth() at the TOP, and below that the version WITH a call to GetLinearizedDepth() in the vertex shader.
Wild guess: it's a bit too eager to declare the sampler, likely it always adds the sampler no matter what and additionally adds it when it runs into it during a visit over the AST which results in a duplicate.
Haven't found a way to work around this other than using ugly #ifdefs and I want to avoid those. Crosire, any ideas what might be the cause of this?
Please Log in or Create an account to join the conversation.
- R3AP3RK1NG
at first I have to thank you - this is one of the kinds of DOF I was waiting for!
I try to find the best DOF for every game I play, but sometimes it's flickering because of dynamic-movements like trees sometime got and then the visual effect is uncomfortable and I wish I could solve this problem, maybe with a kinf of straight fixed DOF in a specific Circle around my position, without interruptions by 3D-Models, it doesn't have to be so accurate. Maybe 2 or 3 circle-areas where I could setup different strenght, to create a smooth transition between the circles - that would match my idea of DOF in some games the best - additional to this 2 static circles for the nearfield of viewing would match this idea at best.
As long as I use the Cinematic DOF by you, while I look on static 3D-Bodells, it's working great, but on moving stuff it becomes flickering like every DOF is doin.
I used for Dying Light f.e. DepthHaze to get a more static DOF - all other DOF-Variants of the official release loosing focus in situation, where they shouldn't.
Maybe someone got a DOF for this in his collection, who knows - I'm new in here, but I'm using ReShade since 2 years right now, but normally only basic and not that advanced, that I could imagine, to create my own shader-effects, seems like to deep into the materia.
C-DOF active:
EDIT!!!
I like the soft transition between static 3D-Modells, it looks so amazing, but as you can see, I really use "soft" DOF.
This is how it looks like with DepthHaze DOF active - it's okay, but I would like to be able, to setup a smoother tsansition until the full strenght of blur takes it's effect and by DepthHaze, is this impossible - all other options failed, because I set up a setting which "currently" seemed to be perfect, but after I take a look around, maybe as much as nothing was effected, or too much and too strong - it's a mess, to try to find the perfect balance, but on more static games like strategy game, it's working perfect and sometimes I combine two different DOF-Shaders, to get the taste I want... but also that is sometimes a crack...
Dying Light with Depth Haze:
EDIT!!!
In Comparison to this - let's take a look at Jurassic World: Evolution, where the AdaptiveFOG in combination with MartyMcFly's DOF is working pretty good!
EDIT!!!
Vanilla:
ReShaded:
Vanilla:
ReShaded:
I really enjoy to play with the adjustments, until I got the game looking the way I want and sometimes I'm completely surprised, how the gameplay feels after such adjustments, I love that!
Please Log in or Create an account to join the conversation.
- OtisInf
- Topic Author
Most dof shaders, like mine here too, are meant for closer to the camera depth of field. the blurriness in the distance isn't merely caused by a depth of field but by haze / fogginess. So for your situation depthhaze is a better solution.
Please Log in or Create an account to join the conversation.
- R3AP3RK1NG
OtisInf wrote: This shader can be used during gameplay but in general as you're looking at a 2D screen, it's not really going to be comfortable regardless. It's meant to be used for elements closer to the camera, not as a blur for far-away stuff like elements on a horizon (use depth haze etc. for that). In fact, I wrote DepthHaze precisely for far away haze / blurriness as it was removed when the debug camera was enabled in the witcher3
Most dof shaders, like mine here too, are meant for closer to the camera depth of field. the blurriness in the distance isn't merely caused by a depth of field but by haze / fogginess. So for your situation depthhaze is a better solution.
My first Idea for DOF came up, because of Tilt-Shift pictures, from above like that:
It's like surreal feeling... everything is like a Miniature Wonderland or kind of Miniature Modell and this becomes awesome implemented in games.
I used your shader as you can see with this settings:
UseAutoFocus=1
UseMouseDrivenAutoFocus=0
FNumber=0.900000
AutoFocusPoint=0.500000,0.500000
FocalLength=23.000000
OutOfFocusPlaneColorTransparency=0.010000
ShowOutOfFocusPlaneOnMouseDown=4294967295
OutOfFocusPlaneColor=0.800000,0.800000,0.800000
FocusPlaneColor=0.000000,0.000000,1.000000
FarPlaneMaxBlur=0.500000
NearPlaneMaxBlur=0.310000
NearPlaneEdgeBlurStrength=1.000000
BlurQuality=3.000000
PostBlurSmoothing=0.080000
HighlightThreshold=1.000000
HighlightGain=1.000000
ShowDebugInfo=0
ShowNearCoCBlur=0
Tryed to compare a setting like that with other DOF-Shaders, without success, it seems like fitting the best, with your DOF no matter what and the gameplay is quite fast, so moving trees aren't really a problem, it's okay the way it is right now and the very more better feeling as DepthHaze could provide, but in my sight, a DOF-Shader with my idea were too great!
Dying Light got some cinematic gameplay-szenes, where the person in front of you is focused, but the backround is blurred - so great, but while ingame an playing with action it's not present, but I want that.
Have a try - have a taste, you can experience the same and become experienced in what I dream about.
Against my understanding, this Shader-Enhancements are increasing performance requirements, but I'm okay with my hardware. How ever, I think, that it could be possible, to get the same visual effects, by decreased quality of 3D-Models in the backround, in combination with lowered sharpness as well as AA and AF, to get the same effect, but with increased performance you know what I mean?
Against setting up a kind of overlay, just reducing calculations - and maybe include the overlay the slightes on top of that.
It seems a good idea, for users of weaker PC-Systems.
Special Thanks at all.
Please Log in or Create an account to join the conversation.
- OtisInf
- Topic Author
I think the bug is here:crosire wrote: That error is something you would get if you include ReShade.fxh twice (which would cause a redefinition). But that would already fail in the ReShadeFXC compiler and not the HLSL backend. Will need to run that through the debugger to check.
github.com/crosire/reshade/blob/master/s...t_compiler.cpp#L1109
Diffing the d3d11 and d3d9 versions of the emitter it shows in d3d9 you add samplers a function depends on to the set of samplers to declare (done ultimately here: github.com/crosire/reshade/blob/master/s...t_compiler.cpp#L1669 ). However there's no check in place where you emit them whether the samplers obtained there are already declared (as they're in a separate set, namely defined by the function) earlier by another function / expression, so it happily emits declarations for them, ending up with duplicates.
I think a subtle filter on name at like 1669 and further whether the sampler has already been declared/seen is enough. Will check if that works...
(edit) adding a limiter with an unordered_set on the unique name works (at line 1662, checking the name at the inner for(), continuing if it's already there) , at least it now emits just 1 sampler definition for a unique name, but it doesn't work at runtime, at least, the shader doesn't work: the depth buffer is always empty in this case, for the dof shader at least, in the vertex shader. If I add a depth buffer display shader using a pixel shader pass it shows the depth buffer in this case.
So not sure what to do, as the check on the unique name was before the sampler was added to the pass.samplers list, but I think it's because the function depends on a sampler that's not emitted in the output?
(edit) Have added some workaround based on __RENDERER__ in an ifdef, was just a couple of lines. Works in d3d9, now to see if it also works in d3d11 and then I'll update the PR so the issue inside reshade can wait for another day (if ever ).
(edit) Fix works in d3d11 as well, so have updated the shader code in the PR, so it should work for the few d3d9 users as well
Please Log in or Create an account to join the conversation.
- kingeric1992
GetLinearizedDepthEx(sampler2D samp, float2 uv)
on app's end, I didn't dig into the code to far,
perhaps separate the output for vertex and pixel shader respectively instead of bundle them in pass obj? [strike]or just prefix with VS/PS?[/strike]
also, it seems like vs_3_0 has sampler limit == 4, instead of the 16 in ps_3_0.
docs.microsoft.com/en-us/windows/desktop...-vs-registers-vs-3-0
(EDIT:)
on second thought, checking name might not be a bad idea, you only need to check sampler anyways.
@OtisInf
purely guessing,
if you ignore a repeated name, the sampler register will be misaligned to what get pushed into d3d state, which still push the sampler into the slot.
aka, given s1 and s2 have name clash, deleting s2 will cause the new s2 after that in shader file mapped to the original s2 state.
you can try adding gibberish to the name instead of bypass them. [strike]or advance sampler count in the loop even if there's a name match without pushing the sampler string.[/strike]
(EDIT:)
or not...since in the impl, it's
for (DWORD sampler = 0; sampler < pass.sampler_count; sampler++) {
_device->SetTexture(sampler, pass.samplers[sampler].texture->texture.get());
_device->SetSamplerState(sampler, static_cast<D3DSAMPLERSTATETYPE>(state), pass.samplers[sampler].states[state]);
}
Please Log in or Create an account to join the conversation.
- crosire
While visiting the AST ReShade builds a string with the sampler definitions for the current pass. Before the fix it accidentally combined the definitions of the vertex and pixel shader, so if you used the same texture in both, that would cause a redefinition. Now they are seperate like it should be.
Please Log in or Create an account to join the conversation.