3dfx shader

It’s a rough implementation of the 4x1 filter shader commonly seen on older 3dfx Voodoo hardware such as the Voodoo Graphics and Voodoo2.

It also dithers the image down to 16bpp before gamma and filters apply, since that’s also what the 3dfx did to the framebuffer.

Not recommended for 2d games (especially lower resolutions) so try Mupen64 with it.

The only thing I can think of that could be done is the need for actual ordered dither in the first pass.

http://leileilol.mancubus.net/shaders/cg/retroarch/

1 Like

Whoa, this looks really good! Thanks for sharing it. Do you mind if I add it to the common-shaders repo?

Thanks, and yeah I don’t mind it in a repository. It is still rough, didn’t do extensive crosschecking with actual voodoo output, as I cannot take screenshots with the DAC filter for technical reasons.

I really like how this looks on N64 and TyrQuake at higher resolutions. I owned a 3Dfx Voodoo 1/2 back in the day and this does look very similar to the look you’d get with that pass-through adaptor on those CRT monitors back then. Thanks for making this.

I’ve updated pass 0 slightly to update the dither method. It’s still not perfect ordered dither, but it’s getting a bit warmer. This was my reference.

I also updated the preset to 1x scale the dither pass.

Sweet. Updated it in the repo. Thanks for the heads-up :slight_smile:

I’ve been playing an N64 hooked up via Svideo and the dithering is much more apparent than via composite (unsurprisingly). Your shader does a very good job of reproducing it.

I have a capture card that will accept Svideo, so I hope to get some comparison shots of console vs emulation soon. I’ll share them here if they turn out well.

Have you seen bisqwit’s dithering article? http://bisqwit.iki.fi/story/howto/dither/jy/

Yeah though his article is more about trying to find the best dither ever and in a far limited palette. 3dfx dithered 888 to 565. My shader applies dither, and THEN reduces to 565. Maybe that’s wrong…

The N64 dither-then-filter pipeline is similar to the 3dfx yes, though more excessive on both passes. I wouldn’t be surprised if this makes N64 emulation looking coincidentally more ‘authentic’. Glide64 would need NPO2 and a pixel shader to simulate the ‘slanted’ trilinear filtering to complete that experience…

I’m refactoring the dithering code to be much cleaner, shorter, and using a 4x4 lookup table…

Two problems though:

  • I’m using Aaron Giles’ dither matrix table from his MAME code - the particular table under a BSD 3-clause license. I used to use the table seen on Wikipedia however this had strange dotting artifacts. Giles’ table seems to line up with the actual thing from the Voodoo2 as i’ve observed in the captures I did…
  • I’m also using one line from a Shadertoy shader for pixel input. Asking permission about this now since shadertoy is CC-BY-NC by default… EDIT: Granted, and plus he licensed his shader as public domain in the header.

RetroArch’s mupen64+ core has a per-texture pixel shader that reproduces that, actually :smiley:

Sweet. That open/cooperative mentality is one of my favorite things about shader development.

I’m not sure, is this how ti is supposed to look?

edit: btw is this shader restricted to native resolution?

The shader should be only used with the core’s native resolution yes. Fiddling with the scaling settings will screw up the dithering process.

It’s not supposed to enhance anything. ‘3dfx’ is a brand.

Speaking of dithering process, there’s dithering in the git common-shaders 3dfx/ pass 0, though it shows up too much in black and probably needs more work.

Probably the most best way to experience the shader is playing certain N64 games without a framerate cap using fullspeed with ports from PC, such as Quake2 64, Star Wars Episode 1 Racer and Daikatana, for the closest period effect for the shader - unless tyrquake gets a libretro GL port…

I’m using 800x600 and doesn’t look bad at all (the shader). I tested and the dithering looks great as well.

Is the texture filtering supposed to be set to something with this shader? I had it on nearest, but not sure if bilinear or 3 point is better, or more authentic in that case, I don’t know.

Bilinear. Not 3 point.

3dfx’s heyday was the era when there was a huge stigma against anything nearest neighbor and ‘pixelated’ so anything blurry and bilinear filtered, even small textures scaled up, were regarded as ‘great graphics’, even on the PC side. Ironically the games that did opt for nearest (barring Saturn and PSX) tend to age better for their edge definition…

3-point gives things that characteristic “diamond” texture look and fixes some things like the weird stair textures in Kak. Village in OoT.

Yeah, I checked and didn’t like the look, too blurred. I stayed with bilinear. The problem though is that what is blurred are the sprites, and they quite stand out from the perfectly sharp polygons around. A global blur would be preferred, or something balanced.

I had a N64, and remember how we were proud of not displaying those awful mimap textures of PSX, haha, funny retro wars.

Rewrote the filter, it’s a different, more undithery method now. Low res 2D games actually show pixel definition now and the filter is far more faithful to the 3dfx.

However this also led to a big reorder of the preset to the point pass_1 and _2 files are switched.

Sweet. Thanks for letting us know about the update! I pushed the new code up to the common-shaders repo and put the old code into a subdir (at least temporarily) in case anyone wants to keep the old look.

EDIT: just got to take a look at it. Good work. Looks much less scanline-y.

One failed to convert to glsl, 3dfx/3dfx_pass_2.cg


retroarch-cg2glsl 3dfx/ 3dfx/
Dirpath: 3dfx
3dfx/3dfx_pass_0.cg -> 3dfx/3dfx_pass_0.glsl ... succeeded!
Dirpath: 3dfx
3dfx/3dfx_pass_2.cg -> 3dfx/3dfx_pass_2.glsl ... failed!
Dirpath: 3dfx
3dfx/3dfx_pass_1.cg -> 3dfx/3dfx_pass_1.glsl ... succeeded!
Dirpath: 3dfx
Dirpath: 3dfx/old
3dfx/old/3dfx_pass_0.cg -> 3dfx/old/3dfx_pass_0.glsl ... succeeded!
Dirpath: 3dfx/old
3dfx/old/3dfx_pass_2.cg -> 3dfx/old/3dfx_pass_2.glsl ... succeeded!
Dirpath: 3dfx/old
3dfx/old/3dfx_pass_1.cg -> 3dfx/old/3dfx_pass_1.glsl ... succeeded!
Dirpath: 3dfx/old
7 shaders converted successfully.
1 shaders failed.
Failed shaders:
3dfx/3dfx_pass_2.cg

I personally prefer the old one. Without proper scanlines for mupen64 the best thing is to blur or smear things a bit. Even so, as someone suggested, I paired it with an antialiaser and I think it’s as good as it gets. Everything comes together and gives that smooth N64 look. I did a comparison video of it, along many other retroarch shaders (you guys rock, for real).

As far as postprocessing shaders go, this is as good as it gets for 3dfx faking i’m afraid. N64 would have to be forked off to a different shader and that’s not something i’m willing to pursue at this time. Two passes of advanced-aa.cg and a mess of NTSC+CRT shaders should fit that fancy.

To go further than this would mean moving the dither stage to textures, outside the postprocess scope

3dfx didn’t do any post-process dithering, that was done on the texture unit. Also it had a different blockier dithering table for blended textures, and with enough overdraw, the dithering will really stand out. This kind of approach is impossible to take on a post filter alone, mupen64 would have to be modified to replicate that…or tyrquake in GL for that authentic 1997 3dfx look… or maybe some DC emulation core for some wackyheaded WhatIfItShippedWithAVoodoo2 reason

however where to start on doing that i’m not even sure, I would want to prototype it in GLSL on this OA engine’s shader system first, which only has working screen postprocess atm. Maybe someday that’ll become a core itself. I already ripped it apart enough to get it to render in 640x480/320x240 scaled upwards with aspect. and even a cvar to slow it to p2-300 approximate speeds