narzoul / DDrawCompat

DirectDraw and Direct3D 1-7 compatibility, performance and visual enhancements for Windows Vista, 7, 8, 10 and 11
BSD Zero Clause License
939 stars 70 forks source link

16-bit dithering? #230

Closed OpenRift412 closed 10 months ago

OpenRift412 commented 1 year ago

I think something that would be nice to have would be the option to enable dithering in 16-bit modes (mostly for Direct3D), giving the game that more authentic oldschool look for those who want it.

narzoul commented 1 year ago

I looked into it, but I don't think it's possible to implement this (with acceptable performance), at least not in the same way as old GPUs used to do it. According to the specs, dithering should be performed after alpha blending, but you don't have access to the destination pixel color from the pixel shader in Shader Model 2. I could go against the specs and do it before alpha blending instead, with slightly different results, but this would also require some serious pixel shader hacking. The shader code is generated by ddraw and is basically like "machine code". Not impossible to do, but I'm not sure it's worth it.

I think it would be better if I just added some fullscreen post-processing dithering filter, by rendering at a higher bit count, and manually dithering it to a lower bit count before presentation. The downside is that it dithers everything, even the parts that the application didn't want to, so it would be a completely independent setting.

narzoul commented 10 months ago

I added post-process dithering under the RenderColorDepth setting in v0.5.0.

OpenRift412 commented 10 months ago

I looked into it, but I don't think it's possible to implement this (with acceptable performance), at least not in the same way as old GPUs used to do it. According to the specs, dithering should be performed after alpha blending, but you don't have access to the destination pixel color from the pixel shader in Shader Model 2. I could go against the specs and do it before alpha blending instead, with slightly different results, but this would also require some serious pixel shader hacking. The shader code is generated by ddraw and is basically like "machine code". Not impossible to do, but I'm not sure it's worth it.

I think it would be better if I just added some fullscreen post-processing dithering filter, by rendering at a higher bit count, and manually dithering it to a lower bit count before presentation. The downside is that it dithers everything, even the parts that the application didn't want to, so it would be a completely independent setting.

But what about dgVoodoo's Direct3D dithering implementation? Is that also just a general filter or is that more accurate? Would you consider the performance of dgVoodoo's D3D wrapper to be sub-par?

narzoul commented 10 months ago

dgVoodoo uses Direct3D 11/12 which has a lot more features than the Direct3D 9 driver interface, which is restricted to Shader Model 3, or rather 2.x if I want to stay compatible with the shaders generated by native ddraw. As far as I could tell, it's simply not feasible to do the old-school dithering of GPUs under these restrictions. For example, in PS 2.x you don't have access to the current pixel's screen position, so you can't really do ordered dithering.

I don't know how dgVoodoo does it (maybe it uses a similar implementation to DDrawCompat's dithering), but at least I think it has the tools for doing a more accurate emulation, based on my very limited knowledge of newer D3D versions. In the end, the differences may be negligible between the two approaches.

I don't know about dgVoodoo's performance, I don't really use it myself.