ArthurCarvalho
New member
Hello, I'm sorry if I'm posting this in the wrong section.
As most of you know, the way bilinear filtering was implemented on the Nintendo64 is different from PC or any other hardware. In order to lower the price of the hardware at the time, Nintendo did their own hack, and used 3 samples to filter the textures, instead of 4. Thanks to this, when the texture is filtered it creates a hexagonal pattern (that I like to call the "rupee" pattern, because it looks like a rupee from Zelda), instead of a diamond pattern (like it happens on PC). This technique is obviously inferior to the 4 sampled bilinear, as it is not a true bilinear filter, but it gives the Nintendo64's blurry mess it's unique "blurryness". Since most of the textures on the Nintendo64 were pretty low-res, this effect was pretty obvious.
At first, I tried to create a a Hi-res texture pack with the pre-applied filters. It worked, somewhat, but it was hard to apply it to every texture, also the textures didn't tile properly.
I thought if it would be possible to implement it using a HLSL Shader, and I was able to do one.
Now, the reason I've posted this here, it because I'm wondering if some dev would like to try to implement this in his plugin.
I though about posting this in the Direct64 topic, but since this could be implemented on any plugin that could use the programmable pipeline (both DirectX and OpenGL), I decided to post here.
If the plugin is already using the programmable pipeline, I believe it would be pretty straightforward to implement this.
In order for the filter to work, it needs two constants: the texture dimensions, both width and height, also the texture sampler must be point (nearest neighbor) instead of linear, since the shader itself is going to interpolate between texels.
Here's the HLSL code:
The pixel interpolation algorithm I got from .oisyn, from this forum:
devmaster.net/forums/topic/13338-bilin-filtering-with-3-samples/
Here's a screenshot: (you'll have to copy and paste the URL, because I couldn't post this link here)
i.imgur.com/oRETY.png
On the left is the standard bilinear filtering implementation, on the right is how Nintendo implemented it in the Nintendo 64.
This is, of course, not inside an emulator, but inside nVidia's FX Composer, where I was coding it. Still, the effect is just like it would look like on the real hardware.
And I understand most people might think of this as a downgrade, and that there is no reason to implement this.
But I think that this is something unique to the Nintendo64, I mean, really, you won't see this kind of filtering anywhere else.
It really gives that "N64" feeling, at least for me it does. It is less smooth, a little more rough than the proper bilinear filter, and I think it gives a little more texture to the game.
So, what do you guys think?
As most of you know, the way bilinear filtering was implemented on the Nintendo64 is different from PC or any other hardware. In order to lower the price of the hardware at the time, Nintendo did their own hack, and used 3 samples to filter the textures, instead of 4. Thanks to this, when the texture is filtered it creates a hexagonal pattern (that I like to call the "rupee" pattern, because it looks like a rupee from Zelda), instead of a diamond pattern (like it happens on PC). This technique is obviously inferior to the 4 sampled bilinear, as it is not a true bilinear filter, but it gives the Nintendo64's blurry mess it's unique "blurryness". Since most of the textures on the Nintendo64 were pretty low-res, this effect was pretty obvious.
At first, I tried to create a a Hi-res texture pack with the pre-applied filters. It worked, somewhat, but it was hard to apply it to every texture, also the textures didn't tile properly.
I thought if it would be possible to implement it using a HLSL Shader, and I was able to do one.
Now, the reason I've posted this here, it because I'm wondering if some dev would like to try to implement this in his plugin.
I though about posting this in the Direct64 topic, but since this could be implemented on any plugin that could use the programmable pipeline (both DirectX and OpenGL), I decided to post here.
If the plugin is already using the programmable pipeline, I believe it would be pretty straightforward to implement this.
In order for the filter to work, it needs two constants: the texture dimensions, both width and height, also the texture sampler must be point (nearest neighbor) instead of linear, since the shader itself is going to interpolate between texels.
Here's the HLSL code:
Code:
float4 n64BilinearFilter( in float4 vtx_color : COLOR, in float2 texcoord_0 : TEXCOORD0) : COLOR {
float2 tex_pix_a = float2(1/Texture_X,0);
float2 tex_pix_b = float2(0,1/Texture_Y);
float2 tex_pix_c = float2(tex_pix_a.x,tex_pix_b.y);
float2 half_tex = float2(tex_pix_a.x*0.5,tex_pix_b.y*0.5);
float2 UVCentered = texcoord_0 - half_tex;
float4 diffuseColor = tex2D(ColorSampler,UVCentered);
float4 sample_a = tex2D(ColorSampler,UVCentered+tex_pix_a);
float4 sample_b = tex2D(ColorSampler,UVCentered+tex_pix_b);
float4 sample_c = tex2D(ColorSampler,UVCentered+tex_pix_c);
float interp_x = modf(UVCentered.x * Texture_X, Texture_X);
float interp_y = modf(UVCentered.y * Texture_Y, Texture_Y);
if (UVCentered.x < 0)
{
interp_x = 1-interp_x*(-1);
}
if (UVCentered.y < 0)
{
interp_y = 1-interp_y*(-1);
}
diffuseColor = (diffuseColor + interp_x * (sample_a - diffuseColor) + interp_y * (sample_b - diffuseColor))*(1-step(1, interp_x + interp_y));
diffuseColor += (sample_c + (1-interp_x) * (sample_b - sample_c) + (1-interp_y) * (sample_a - sample_c))*step(1, interp_x + interp_y);
return diffuseColor * vtx_color;
}
The pixel interpolation algorithm I got from .oisyn, from this forum:
devmaster.net/forums/topic/13338-bilin-filtering-with-3-samples/
Here's a screenshot: (you'll have to copy and paste the URL, because I couldn't post this link here)
i.imgur.com/oRETY.png
On the left is the standard bilinear filtering implementation, on the right is how Nintendo implemented it in the Nintendo 64.
This is, of course, not inside an emulator, but inside nVidia's FX Composer, where I was coding it. Still, the effect is just like it would look like on the real hardware.
And I understand most people might think of this as a downgrade, and that there is no reason to implement this.
But I think that this is something unique to the Nintendo64, I mean, really, you won't see this kind of filtering anywhere else.
It really gives that "N64" feeling, at least for me it does. It is less smooth, a little more rough than the proper bilinear filter, and I think it gives a little more texture to the game.
So, what do you guys think?