Gameboy shader

Updated the git with a new background system that allows for background images with highlights (before it just multiplied the background image by the background color, so it could never be brighter than the background color). Should allow for more metallic looking backgrounds. Also put in a smoothing option that lets your control how much of the background’s color variance is hidden directly beneath the foreground since this can result in a lot of visual clutter and make the game hard to see. This is listed in the gb_pass_4.cg file under the config header as “bg_smoothing”.

I added some more built in color palette and background options. My photoshop skills aren’t the greatest, but they should give people an idea what to do if they want to make their own backgrounds. The image dmg_background.png is the best approximation of the actual dot matrix Gameboy screen that I could produce using photoshop’s built in filters. The gbp_palette.png was created with the help of an anon on emulation general and the grainy_background.png is loosely based photos that he provided of the Gameboy Pocket (it’s really not very good, though, my photoshop skills failed me).

Oh, and I changed around the default configuration to what seemed a little more authentic to me. I don’t suppose it’s possible to put these into their own config file somehow and load them in as uniforms, is it?

Was playing around in Photoshop trying to come up with a good technique for reproducing the GBC screen. All my attempts seem to end up looking more like an aperture grille from a CRT than an LCD pixel though.

This is the best mock up I could come up with, but it only passingly resembles the GBC. Going to have to play around some more, looks like it’s going to be a little more complicated than the original Gameboy.

In 0.9.9-wip1, I fixed an issue in D3D9 which might interest you. FBOs were in XRGB8888 format instead of ARGB8888 format. Your shader might work now.

I kind of patchworked in some changes to the GB shader for use with color just to see what it’d look like (it’s not on the git, the code is a mess of conditionals that I’m surprised even runs). Without all the alpha blending it kind of just looks like… a grid and a border. I think I’m going to try approaching it more like an exaggerated LCD screen.

I suppose I should share the LCD shader that I put together. It’s a combination of a shader that I made a couple months ago (which began from a modification of the Pixellate shader; I’d post the link, but I’m only allowed one link per post for some reason) and the simple motion blur from hunterk. The shader is here.

Interesting, similar basis to one of the methods I experimented with earlier in Photoshop. The magenta/yellow/cyan route definitely helps retain a lot of the brightness over RGB and seems to help with color fidelity.

Currently having issues figuring out a method that scales well, though. In this image I’m using non-scaling virtual pixels made up of 3x3 actual pixels, resulting in pixel quadrupling for what should be a single pixel in a 6x scale image. Just extending the colors out into a gradient to enlarge the virtual pixels drastically reduced the image quality. Still experimenting but I haven’t found anything I’m happy with yet.

Great, updated the GB shader with a minor change and it now functions with D3D with this fix.

I made a little bit of progress in my search for an approach to an LCD shader for GBC and other handhelds. This seems to be the best compromise I could come up with so far for scaling images without too much color separation. There’s a definite darkening of the image, but I think I can solve that while simulating lighting (the colors on a backlit screen will look different from the colors on a frontlit screen).

–edit-- Started applying the approach above in an actual shader rather than just a mockup. Still needs work, but the general effect seems somewhat handheld LCD-like. Here’s a shot of it running in-game currently:

–edit2-- You can find an early version of the LCD shader here:

If the default settings are too subtle or too strong for your liking, you can take a look through the .cg files and play around with some of the config options. I’ve mostly tested it with VBA, so I’m not sure if it’ll work well with other emulators or not. Higher resolutions seem to result in better image quality (would recommend minimum 4-5x scale). Practically speaking, I wouldn’t mess with cell_scale value in lcd_pass_1.cg unless you’re playing at 6x or 9x scale and are sitting far back from your display, like on a HTPC or something.

I’ve tried both the gameboy an the new lcd shader with RA 0.9.9-wip. They run fine in windowed mode, but not when in fullscreen mode (fps <60).

Is it an issue that you’ve only had with that specific build, eadmaster?

I’m not surprised that it might run slow for some users, though. I’ve only done some ghetto performance testing by unlocking the framerate and looking at the FPS hits, the overhead of just chaining stock shaders together in a .cgp file seems to be about a 7-8% FPS drop per pass on my GTX460. These are probably more severe than that since there’s a lot more operations and texture lookups involved than in a stock shader. The sudden performance drop between windowed and fullscreen might be due to the FBOs going from 1024x1024 to 2048x2048, depending on the viewport resolutions.

I could probably make a more lightweight version of the Gameboy shader with only some minimal sacrifices. The LCD shader is probably a little bloated too (the border system really isn’t necessary, just tacked it on while I was internally forcing integer scaling which can be forced through RA anyways, and might not even be necessary in the next version of the shader).

Sorry for the lack of updates lately. Playing around with shaders kind of got me interested in graphics programming so I’ve been doing a lot of reading on OpenGL the past few days. Fun stuff.

No problems here at all with the lcd_shader :slight_smile: I’ve tested with GBC and GBA on my i7 3770K with GTX480 and AMD A5700 with Radeon 7660D (integrated GPU on CPU) (both OpenGL). Works in window mode and fullscreen (prefer windows fullscreen) without problems and fps drops. Nice work!

EDIT: well… it just looks completly different to your Screenshot: http://i.imagebanana.com/img/f7sshacu/RetroArch0427230825.png

I’ve just re-tried lcd_shader with a lower fullscreen resolution, and this time it worked fullspeed… probably my integrated GPU (Radeon 6530D) is too slow for 1920x1080.

Harlequin - I’ve given you commit acess to common-shaders. Hyllian thought it was a good idea so there you go.

If you’d like you could upload your Game Boy shader and other things you’re working on.

Thanks Squarepusher, I went ahead and added the Gameboy and LCD shaders to the repository under the handheld directory.

Tried out the Game Boy shader on PS3 for the first time and it doesn’t work.

EDIT 1:

Found the issue with Nvidia’s cgc for PS3 -

<Squarepusher> [twinaphex@lenovo shader_files]$ sce-cgc.exe -e main_fragment -p sce_fp_rsx -o gb_pass_0.fpo gb_pass_0.cg <Squarepusher> gb_pass_0.cg <Squarepusher> gb_pass_0.cg(150) : error C1008: undefined variable “mod” <Squarepusher> gb_pass_0.cg(150) : error C1105: cannot call a non-function <Squarepusher> gb_pass_0.cg(150) : error C1008: undefined variable “mod” <Squarepusher> gb_pass_0.cg(150) : error C1105: cannot call a non-function <Squarepusher> gb_pass_0.cg(150) : error C1008: undefined variable “mod” <Squarepusher> gb_pass_0.cg(150) : error C1105: cannot call a non-function <Squarepusher> gb_pass_0.cg(150) : error C1008: undefined variable “mod” <Squarepusher> gb_pass_0.cg(150) : error C1105: cannot call a non-function

Replaced it with fmod and that seems to work for both PC and PS3.

Now it fails at loading one of the PNG textures (background.png). I’ll try to investigate that one as well. It might just be too big (2048x2048). Does it really need to be so huge? It’s pretty abnormal to have a huge 2048x2048 texture for something that just looks - well - ‘grey’ with no real apparent detail or reason why it needs to be so big.

Can you downsize it to 1024x1024?

EDIT2; Downsizing background.png to 1024x1024 makes it work at least. I will commit the updated background.png (1024x1024). Let me know if you have any objections to this later on - I asked Hyllian and hunterk and they thought going from 2048x2048 to 1024x1024 for the background texture shouldn’t matter.

Yeah, it really doesn’t need to be that big. That was a remnant from the first version of the shader when I was setting the FBOs to an absolute size of 2048x2048 and I thought it’d be easiest to keep the background image the same size as the FBO, was still learning Cg at the time. I should rework that part of the shader anyways, it’s literally just mapping the entire image to the screen currently so you end up with stretching no matter what size the texture is (didn’t notice this during development because I was using really simple backgrounds).

Kind of cool that you got it working on the PS3, though. Didn’t know much about optimizing shaders or compatibility issues when I started, I was surprised that it even ran on my PC with reasonable performance.

Just curious if I can be helpful with my makro lens to create a perfekt lcd shader (or Game Boy) I have every Game Boy handheld in my library (GB, GBC, GBP, GBL, GBA, GBA SP…). Here is an example of the Game Boy Color Screen (CGB-001): http://i.imagebanana.com/img/7i6u7wzt/IMG_0023.JPG As you can see, the subpixel gets more tiny at the lower end and the gap between pixels in horizontal way is bigger than vertical. Here is the Screen of my DSi-XL: http://farm5.staticflickr.com/4116/4777128707_2d68c5dd0e_o.jpg It’s slightly different. Your filters feels more a touch of red, but it is more of yellow, like on my photo.

Whoa, those are very nice photos. Much better than the reference shots I took with my cell phone, ha. Will definitely be able to make use of those.

There’s some issues with doing a totally accurate handheld LCD shader. First, if you simply directly scale the LCD cells (a cell being one pixel on the real handheld screen made up of red, green, and blue subpixels) up to a larger size to match the scale of the image being displayed on your monitor, you get very dramatic color separation because the subpixel representations are now very far apart in terms of screen pixels. If you were playing from very far back or on a small, high DPI screen this would be probably be the optimal approach. At a normal viewing distance on a normal monitor it becomes pretty painful to look at, though.

Second, the image tends to darken significantly even at small cell scales. This is because even if you did the minimum representation where 1 pixel on your monitor correlated to 1 subpixel from the handheld screen, if you had a primary color like red being displayed you’d end up with 2 black pixels between every red pixel. Pixels on a typical monitor are pretty large so this gap is much more noticeable than the gap between subpixels on your handheld LCD (although it is still noticeable on the handheld and this is an important factor in replicating the feel of the original screen).

In order to brighten the image up, a lot of LCD shaders, including mine, use magenta/yellow/cyan instead of red/green/blue. This means that if you had a red pixel on screen, instead of just lighting up 1 pixel in the simulated cell (the pixel corresponding to the red subpixel) and having 2 black pixels, it now lights up two pixels in the simulated cell - the magenta (red/blue) and yellow (red/green). This is probably why you said it feels more red than the real thing. This concept could actually be expanded on to stretch out LCD cells into arbitrarily wide color gradients which can be one approach to solving the cell scaling problem mentioned above, but in my photoshop mockups scaling cells in this way still resulted in unpleasant levels of color separation.

The image will probably still be a little too dark after this, so a lot of shaders will actually overlay the cell representation of the screen on top of the “raw” image. Some even just tint the raw image with r/g/b or m/y/c bands to approximate the effect. I use color darkening in my approach to obtain the correct colors and intensities of the subpixels before blending them back with the raw image (well, not quite raw, I add horizontal lines which then do a sort of color averaging blur to mimic the borders between vertically adjacent cells on the actual screen).

What this all comes down to are that some compromises have to be made on current displays. The cell representation I use has a static width of 3 screen pixels (each representing a m/y/c subpixel) so you’re going to get wider color bands compared to a r/g/b representation. You’ll also see multiple cells for every “pixel”, which should be mapped to a single cell on the real screen, if the scale isn’t exactly 3 (you can even get partial cells if the scale isn’t a multiple of 3, but the effect is subtle unless you’re looking really close). Additionally, I partially blend the raw image back in to boost the image brightness, which isn’t realistic at all because now a subpixel that should be black will have some color blended into it. What you get is something like a pixel on the Gameboy that should be 255 red, which would normally be represented by a fully lit red subpixel and “off” (black) green and blue subpixels, would be represented in my shader as two 255 red pixels (those representing hypothetical magenta and yellow subpixels) and a somewhat darker (say, 127) red pixel (corresponding to the hypothetical cyan subpixel). Not physically accurate, but the overall color is much closer to what you’d expect.

I guess you could think of it kind of like scaling the image by fusing multiple Gameboy screens together and stretching the image across the new larger screen rather than just blowing one screen way up. The m/y/c cells and raw image blending tricks just compensate for the fact the simulated cells are 3 times wider than the original cells because each subpixel has to be mapped to a single monitor pixel.

And wow, that turned into a longer post than I expected. I’m actually working on a simple sprite game right now to get some practice with OpenGL development and I want to implement a shader kind of like this in it. It might be a couple weeks, but I hope to refine my LCD shader approach in the process so I can do a meaningful update on the RetroArch shader as well.

That simple sprite game - considered using libretro with the new GL hardware renderer callbacks? I think RetroArch can serve as a good game/demo platform - we just need to hit critical mass there. I have some things lined up that might just do that.

Can you port these shader for vba-m? Im not finding any shaders like yours for the vba emulator.

@rex RetroArch has a VBA core you can use it with.