Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » "TV Mode" Filter Algorithm?

Credits go to Bob and Goodbytes for helping out!
This thread is locked; no one can reply to it. rss feed Print
"TV Mode" Filter Algorithm?
DmAndrew12
Member #1,950
February 2002
avatar

So, I've been working on an OpenGL game engine in C, and I'd like to implement some display filters (currently scanlines and "tv mode," as seen in many emulators).

Scanlines are easy, however, the whole "tv mode" filter I'm puzzled about. I've seen it done in numerous emulators (snes9x, Gens, Kega Fusion, etc.), and it produces a VERY nice TV-esque effect, especially when combined with scanlines. It seems like some sort of interpolation, but I can't even think of how to do it.

Snes9x is open-source. I've even found the code for the tv mode filter, but it's undocumented, and I can't make any sense out of it. There are numerous emulators that use SDL (on some page called SDLEMU or something), and they all appear to use the same graphics code, because they all have similar filters. Unfortunately, these are all closed-source (lame).

So, do any of you know how this tv filter is achieved, or have any idea how the function in snes9x's code works? I'd really love to have this filter, as I'm aiming to write an old-school rpg engine, and having a tv filter would make it even more old-school ;)

I'm just looking for a general algorithm, like:

Scanlines X%: Scale the screen by a factor of two. Darken every other horizontal line by X%.

The snes9x source file in question is attached... oddly enough, it uses Allegro (though hardly it seems).

The entire source can be found here: http://www.zophar.net/Files/snes9x-1.42-src.tar.gz

Thanks!

Carrus85
Member #2,633
August 2002
avatar

FYI, if you need to take another look at an emulator, ZSNES is also open-source.

Not only that, I imagine you could compile it for Linux considering it is written in SDL, IIRC. ;D

Richard Phipps
Member #1,632
November 2001
avatar

Dm: I've not looked at the code, but I would suggest somekind of blur filter would help the effect. :)

DmAndrew12
Member #1,950
February 2002
avatar

Unfortunately, ZSNES's drawing code is in x86 assembly! I only know MIPS assembly at the moment :'(

Jeremy McCleese
Member #5,241
November 2004
avatar

Scanlines and TV Mode are nearly identical. TV Mode just uses a lighter colored pixel to draw the lines. This mode is mainly used to reduce the bleeding effect that red has on a television. This could be achieved using Allegro by creating a buffer the size of your screen, using hline to place the lines where they are needed. You could then call it like:

draw_trans_sprite(buffer, screen, 0,0);

Making sure you setup the set_trans_blender function before set_gfx_mode.

This will overlay the partially transparent bitmap of hlines on top of the screen essentially darkening it to eliminate bleeding.

r30y162part2

DmAndrew12
Member #1,950
February 2002
avatar

I've looked at screenshots, and there seems to be more to it than that :-(

I've attached some examples of various tv mode effects by different emulators. Sorry for the large filesize, but the pixels and colors are crucial.

Kitty Cat
Member #2,815
October 2002
avatar

It's probably some kind of interlacing effect. Like, for every frame, it copies either the even or odd rows to the screen, discarding the rest for that frame.

--
"Do not meddle in the affairs of cats, for they are subtle and will pee on your computer." -- Bruce Graham

miran
Member #2,407
June 2002

Not really what you need but I made a kind of a TV mode in my Paranoid game (link in my sig). Press 'm' in the game to change the mode from the default green scanlines to TV (it's black and white but that's only because all the gfx are like that). As I said, it's not really what you need because it achieves the effect by expanding every pixel into a 3x3 square (3 vertical lines, 1 red, 1 green, 1 blue) so the game's resolution is actually 3 times smaller then the gfx_mode. But it looks kind of cool...

--
sig used to be here

Tobias Dammers
Member #2,604
August 2002
avatar

Looks to me as if they're doing a 2x resize with interpolated pixels in between (sorta anti-aliasing). The Kega seems to do it in both dimensions, while the SNes9x only does it horizontally.
Basically, the algorithm would then work as follows:
- fill every pixel at even x values with the source color at (x/2, y/2).
- fill every pixel at uneven x values with (src(x/2, y/2) + src(x/2+1,y/2)) / 2

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

miran
Member #2,407
June 2002

Here's my code if you want to check it out. This is the unoptimized easy to understand version (code comments explain what you can do to optimize it). There are actually 6 different implementations of what is basically the same algorithm, choose whatever looks best if you want...

Btw, despite the .cpp extension of the source code file, the actual stretch filter function is written in plain C...

--
sig used to be here

Goodbytes
Member #448
June 2000
avatar

Quote:

So, I've been working on an OpenGL game engine in C

This kind of full-screen effect will be inefficient if you try to implement it with OpenGL the way that you would implement it with Allegro. You might be better off trying to find a solution that involves overlaying a translucent texture to the screen--say, one that looks interlaced--after the scene is rendered. You can also enable multisampling, which will give you full screen antialiasing if you need that to achieve the desired effect.


--
~Goodbytes

DmAndrew12
Member #1,950
February 2002
avatar

I was thinking of rendering the scene to a surface, and then doing the effects to that surface, then blitting that surface to the screen. First, I have to figure out how to render to a texture. ;)

As far as the scanlines go, I'm thinking of rendering the scene to a surface, then setting the alpha of every other line to the desired %. Then I'll blit onto a black background.

I could just overlay a semi-transparent lined textured, but that won't give me an accurate effect :-/

Any other ideas?

Goodbytes
Member #448
June 2000
avatar

Quote:

then setting the alpha of every other line to the desired %. Then I'll blit onto a black background.

Trust me, you can do the exact same thing by overlaying the screen with a texture. Use an 8 bit grayscale texture of, say, 32x32 size with texture repeating enabled and appropriate texcoords so that the texels correspond 1:1 with pixels, with white areas as 100% alpha, and black as 0%. Render the scene normally, then overlay the texture with blend mode (GL_ZERO, GL_SRC_COLOR). It will multiply all the scene pixels with the corresponding white level, just like setting every other line to a certain alpha will, except you don't need to use your alpha channel and it will be much more efficient. Why wouldn't this give you an accurate effect?


--
~Goodbytes

Bob
Free Market Evangelist
September 2000
avatar

Quote:

Trust me, you can do the exact same thing by overlaying the screen with a texture. Use an 8 bit grayscale texture of, say, 32x32 size with texture repeating enabled and appropriate texcoords so that the texels correspond 1:1 with pixels, with white areas as 100% alpha, and black as 0%. Render the scene normally, then overlay the texture with blend mode (GL_ZERO, GL_SRC_COLOR). It will multiply all the scene pixels with the corresponding white level, just like setting every other line to a certain alpha will, except you don't need to use your alpha channel and it will be much more efficient. Why wouldn't this give you an accurate effect?

Why a texture? Just draw untextured horizontal lines with the right alpha. You'll use a lot less bandwidth and negligeably more vertex processing.

--
- Bob
[ -- All my signature links are 404 -- ]

Mandrake Root Produc
Member #300
April 2000

It seems to me they used something like 2xSai and then overlayed scanlines ontop of that. Tell you the truth, not very impressive. I was hoping for something that would do the cool ass TV effects from Silent Hill 3. Like moving scanlines, flickering images, that sort of thing.

Goodbytes
Member #448
June 2000
avatar

Bob said:

Why a texture? Just draw untextured horizontal lines with the right alpha. You'll use a lot less bandwidth and negligeably more vertex processing.

Right... If you're just doing plain horizontal lines, which you are, listen to Bob. I'm a little stuck in texture mode because I use a texture overlay in a project I'm working on to simulate an oil painting. For more complicated effects like that, I would suggest a texture overlay.


--
~Goodbytes

DmAndrew12
Member #1,950
February 2002
avatar

Thanks guys

Go to: