EDIT: My new efforts have been moved into a different thread. Please comment there instead
I don’t know why, but I suddenly got it into my head that I wanted to make an NTSC/CRT effect in Unity.
At first I tried to hack it. Every other “scanline” I offset texture by a pixel, and I also slightly separated the red and green channels. It looked OK, but not great.
My next attempt is another beast altogether. This time it’s a multipass effect, ported over from an emulator. The idea is that the shader converts a digital RGB image into an NTSC composite signal (chroma+luma), then converts it back to RGB values. There’s some other stuff in there such as offsetting some values by a frame counter, but the basic idea is converting to and from an NTSC signal (there’s some inherent data loss in there which results in that classic color bleeding we all know and love)
Here’s the result. It’s some footage of Super Mario World on the SNES.
Click “Toggle NTSC” to switch the NTSC effect on and off (it’s off by default). I also hacked some scanlines into the shader, just cause they look cool.
Apologies if the video gets really repetitive (it’s only a minute long, and just loops). I suggest turning down your sound (or mute it altogether)
A CRT-effect is something I’ve been looking for for some time, as I want my game to look like something from the 32/64 bit era.
Could you upload it somewhere?
I was also wondering, are you aware of an effect that turns off perspective-correction?
Yeah I know, I took it down because I was worried about space and because I thought the thread died lol
I’ll put up the source code when I get the chance.
I’m looking forward to this a lot. As I’ve asked before, I’m a bit curious regarding if you have any idea how to acheive the “shaky” effect seen in Sega Saturn and PSOne games, as they didn’t have proper perspective correction?
I don’t, unfortunately. It was really a consequence of hardware design that caused that, which I’m not sure can be easily replicated on modern hardware short of writing your own software renderer.
It’s a two-pass image effect, and you need to pass the frame count for the animated scanline effect (actually it works best if framecount is incremented 30 times per second instead of 60, looks more retro-ish)
Sorry for necroing, but I was snooping for NTSC shaders and found this.
I believe the shake error was a projection based on look up tables, with errors in them.
Either that or it was rounding errors during the calculation due to integer math.
In any case, you’d have to get into the camera. The projection nowadays is done in hardware, so this would be tricky to pull off :-/
Perhaps with a Vertex shader and an estimation of the error based on distance from the camera it could be achieved.
Another year, another necro. Digging around for NTSC shaders as well, and this is one of the very few real results available. Like, at all.
I’m hoping someone can help figure out what’s gone wrong here. I’m testing a mock-up image (left) on a quad, and I have an orthographic camera with the CS script and shader applied. The only change I’ve made to the shader is the Input/Display resolution (256, 240, 256, 240), to match the input image.
I’ve had very little luck trying to troubleshoot it. The best I can get out of it is a red channel image with very faint blue/green channels showing through the scanlines — Fine for the Virtual Boy, but not what I’m aiming for! If anyone knows how to correct this, it’d be greatly appreciated.
I’d sorta abandoned this, but I’ll give another shot at fixing it up.
EDIT: Interestingly, I have one project in which this works and one in which it doesn’t. No idea what the difference is yet, but that should be a clue as to how to get this fixed up and working properly
I also have some ideas on how to make it more efficient and compact, by potentially using lookup tables to do the RGB->YIQ->RGB conversion instead of doing all of the math in the shader.
EDIT: OK, so today I actually decided to implement the effect from scratch using LUTs instead of a per-pixel matrix multiply. The good news is that it’s working (again). The even better news is that the new shader is much more concise. The even more better(er?) news is that it actually looks a little bit better IMHO, as I’m porting over some code from a different NTSC shader. This one is three passes instead of just two, but actually looks a bit more retro IMHO because it basically:
1.) converts RGB to YIQ color space
2.) converts the YIQ color into a composite signal
3.) low-passes and smears the composite signal a bit, and then decodes the composite signal back into RGB.
This has the effect of adding some of the image fuzzing and color smearing that you’d see on older TVs that the previous method didn’t have as much.
Also, since this shader is a lot more of my own code than the previous one was, I have a much better understanding of how it works and so it should be easier to maintain (thankfully!)
Some results of the reimplementation, using a screenshot from Sonic 2 for testing. Added a simple pixel mask effect which sort of simulates the shadow mask used in some TVs, plus fisheye distortion to give it the curved CRT look
Have yet to find a situation which makes everything go magenta in this version, so that’s a plus I suppose
Today I decided to write a screen fading image effect inspired by the Sonic The Hedgehog titles on the Sega Genesis. Those of us who’ve played it will remember that hue shift as the screen faded -when fading in you could see the whole palette shift through a blue-ish color. After doing some research, it turns out that the R, G, and B fades are independently staggered from each other. Since they don’t fade at the same time, it produces a hue shift. Whether or not this was intentional or a bug isn’t known, but I decided to replicate it anyway.
So the screen fade effect lets you specify an RGB separation value, which is how much each component is staggered. It goes from 0 (off) to 0.66 (components are faded in sequence, first R then G then B, with no overlap). You can see the results here (shows both fading to black, and fading to white):
EDIT: Oh, and by the way, I’m thinking I’ll be turning this into a whole suite of effects and releasing it on the asset store. In addition to effects intended for pixel art 2D games, I’ll also be throwing in some effects for Saturn/PS1 style games as well, such as the good old wobbly vertex effect, affine texture mapping, and a few dithering effects I came up with (as an example, check out the car shadows in Virtua Racer for the Sega Saturn).
It will also include a custom input manager which correctly handles mouse position even with the fisheye effect enabled (it can apply an optional fisheye distortion to the mouse position for mouse events).
EDIT2: I’ll probably also throw in an interesting tool I made… basically, a while back I spent a lot of time researching making digital-to-analog circuitry that could interface with the VGA standard. It turns out that, for each color component, you make a voltage divider which contains a series of resistors of doubling resistance values, one resistor per bit, such that when all bits are on the voltage sums to 0.7v (which is max voltage in VGA).
So, based on that research, I made a tool for Unity. You specify how many bits per color component, and voltage per bit, and it tries to spit out resistance values that would match this. You can tweak the resistance values from there (for instance, picking closest values you could actually order from manufacturers), and then based on that it can spit out a color lookup table which is made by calculating voltage values, which can be plugged into the Color Grading effect as-is. So in the end you can produce a color LUT which would be the result of using theoretical custom-designed VGA circuitry. Overkill? Probably. But I think it’s neat anyway, and you can always just plug in number of bits, hit Generate, and just save it without messing with any of the values.
Wickeddd. There’s so many “retro” assets and tutorials out there that merely throw chromatic aberration over the top (or even more simply, shift color channels left and right) and call it a day, so it’s refreshing to see an effect that goes the full mile. Especially since older titles were designed around the limits of composite video, and even took advantage of them in some cases.
Integer vertex snapping and affine texture mapping are always fun too. Mercilessly unforgiving, but fun!
The VGA LUT generator sounds interesting though. I’m assuming the end result is fairly subtle but noticeable. How far can the generator’s values be pushed?
Edit: I saw the Video Mode Demo video on your channel, and it looks great right now. How customizable are the video mode presets? If I were to dig into the shader itself, could the amount of color smearing (for example) be fine-tuned? Can the display video be locked to a specific resolution or aspect ratio? (eg: Input resolution is 320x240, while output is set to display at 4:3 with pillar/letterboxing, regardless of the player’s actual screen res)