hizzlekizzle / quark-shaders

A repository of GLSL #150 pixel shaders for use with byuu's Higan emulation package.
GNU General Public License v2.0
187 stars 27 forks source link

Interlacing in ares and bsnes accurate PPU #6

Open Michael-Prince-Sharpe opened 3 years ago

Michael-Prince-Sharpe commented 3 years ago

When using the crt-royale or crt-royale-kurozumi shaders it's very noticeable with jittery flickering interlacing. The ares/higan/bsnes accurate PPU seems to think it's interlaced.

hizzlekizzle commented 3 years ago

Yeah, the accuracy PPU runs everything at 512x480 whether it needs to be at that moment or not (IIRC, the PPU can change between high-res within a single scanline and between interlaced within a single frame and the only way to reproduce this is to provide a window/context large enough to do this at all times).

However, you can put a downsample pass in front of the other shader passes to squash the image down to 50% height and width to compensate:

#version 150

uniform sampler2D source[];
uniform vec4 sourceSize[];
uniform vec4 targetSize;

in Vertex {
   vec2 texCoord;
};

out vec4 fragColor;

void main() {
   vec2 one_px = texCoord.xy * sourceSize[0].zw;
   fragColor = texture(source[0], texCoord - vec2(float(mod(one_px, 2.00001))));
}

and then in the manifest do:

program
  filter: nearest
  fragment: downsample.fs
  height: 50%
  width: 50%

as your first pass.

Michael-Prince-Sharpe commented 3 years ago

Yeah, the accuracy PPU runs everything at 512x480 whether it needs to be at that moment or not (IIRC, the PPU can change between high-res within a single scanline and between interlaced within a single frame and the only way to reproduce this is to provide a window/context large enough to do this at all times).

However, you can put a downsample pass in front of the other shader passes to squash the image down to 50% height and width to compensate:

#version 150

uniform sampler2D source[];
uniform vec4 sourceSize[];
uniform vec4 targetSize;

in Vertex {
   vec2 texCoord;
};

out vec4 fragColor;

void main() {
   vec2 one_px = texCoord.xy * sourceSize[0].zw;
   fragColor = texture(source[0], texCoord - vec2(float(mod(one_px, 2.00001))));
}

and then in the manifest do:

program
  filter: nearest
  fragment: downsample.fs
  height: 50%
  width: 50%

as your first pass.

Thanks very much, Hizzlekizzle, works like charm. If it's alright, I put the new files in a fork specifically for the bsnes accurate PPU, Higan or ares if anybody wants them?