English Amiga Board


Go Back   English Amiga Board > Support > support.WinUAE

 
 
Thread Tools
Old 04 February 2012, 16:45   #1
Dr.Venom
Registered User
 
Join Date: Jul 2008
Location: Netherlands
Posts: 485
Adding a "non-lineair" scanline option to WinUAE

Hi Toni,

The discussion in the 'New Filter' thread (http://eab.abime.net/showthread.php?t=62541) got me thinking about the current scanline effect implementation for LCD/LED monitors. Below is a suggestion on how to possibly improve on it.

The current implementation in the tab filter -> extra settings allows for setting "Scanline Transparancy" from 0-100 on a lineair scale. It lowers intensity of the whole scanline by the X% transparancy set. This seems adequate, but on closer inspection, real CRT scanlines show an effect that might need the emulation to go one step further.

As observed in the new filter thread, in reality on a CRT scanline "texture" is dependant on the brightness of the underlying pixels. Clear white almost doesn't show scanlines from normal viewing distance on a CRT, but e.g. more dark red or blue has clearly visible scanline texture. A nice example illustrating this is the protograph in the Commodore Horizons magazine from a CRT screen showing the famous "Tutankhamun" picture. Shown on the picture of page 31 of the march 1986 issue:

Mag = Commodore Horizons
Issue = March 1986
Page = 31

http://amr.abime.net/issue_2704_pages

In the example picture the bright gold on the forehead and right scheek is almost solid with no scanline effect, while the more dim colors, like the darker blue show clear scanline effect.

This effect seems to be a result of the phosphor glow of traditional CRT screens and basicly makes "scanlines" on a real CRT a per pixel dependant non-lineair effect. And, in view of that, might classify the current scanline implementation as a bit of a "short-cut" to the real thing (i.e. by using a lineair transparancy scaler for the whole scanline).

As such, I'm wondering if it would be possible to add a scanline option that utilizes the suggested per pixel non-lineair transparancy scaler, or something similar? Such that bright white only has about 10% transparancy (almost no visible "scanline") and such that with each step in brightness of the underlying source pixel, the transparancy is increased in a non-lineair/quadratic way, i.e. darker colors turn increasingly faster to a solid black. Just as is shown in the "Tutankhamun" example. The end-result would (IMHO) lead to more real scanline effect emulation than the current implementation.

I don't know if it's possible, but would you consider adding such an option to WinUAE? (And to be clear, this is about more accurate emulation of the built-in scanline options, not to start a generic thread about "what filter is best and what would you like").
Dr.Venom is offline  
Old 04 February 2012, 17:02   #2
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,505
Only way to do it dynamically is to create pixel shader scanline "filter". Software version would be painfully slow.

Note that shader code can be "stacked", previous code writes to temp buffer that next one reads and so on.. (RGB mask or current scanline is already separate pass on top of selected filter)

I can write the shader code but only if someone else creates the algorithm.
Toni Wilen is offline  
Old 15 March 2012, 19:08   #3
Diduz
 
Posts: n/a
Hello guys, hello Toni! I've been using WinUae for ages and it's GREAT.
Diduz from Italy here.
Yesterday I tried a special build of DosBox ( http://ykhwong.x-y.net/ ) which features a very good CRT emulation shader for Direct 3D. It's really good and it looks to me exactly what Dr. Venom was talking about.
I know it's not strictly WinUae-related, but I think it could look good in the Amiga Emulator.

The files CRT.D3D.bright.fx and CRT.D3D.fx are located in the SHADERS subdirectory and seem to be under GPL.
 
Old 25 April 2012, 00:33   #4
Pixelfan
Registered User
 
Join Date: Apr 2012
Location: Germany
Posts: 12
Cheap trick

Hi,

I thought this sounds interesting, so I tried some things out. Actually, you can achieve a similar effect by rather cheap transformations:

Code:
red = red > 127 ? red - (255 - red) : 0;
grn = grn > 127 ? grn - (255 - grn) : 0;
blu = blu > 127 ? blu - (255 - blu) : 0;
Here is an example of how it looks on a 3x scaled cutout of the Turrican title screen:

http://eab.abime.net/picture.php?alb...pictureid=2214

Notice how there are almost no scanlines in the white areas but clearly visible black scanlines in the darker sections of the image.

Should not be too expensive if you implement it like that.

Best regards,
Pixelfan

Last edited by Pixelfan; 25 April 2012 at 08:41.
Pixelfan is offline  
Old 25 April 2012, 01:20   #5
Retro-Nerd
Missile Command Champion
 
Retro-Nerd's Avatar
 
Join Date: Aug 2005
Location: Germany
Age: 52
Posts: 12,438
Looks really nice, Pixelfan.
Retro-Nerd is offline  
Old 25 April 2012, 08:41   #6
Pixelfan
Registered User
 
Join Date: Apr 2012
Location: Germany
Posts: 12
Alternatively something like this:

Code:
red = (red * red) >> 8;
grn = (grn * grn) >> 8;
blu = (blu * blu) >> 8;
That requires 16-bit integers and multiplication. However, no conditional statements needed.

Result looks similar.

Last edited by Pixelfan; 25 April 2012 at 08:47.
Pixelfan is offline  
Old 25 April 2012, 11:12   #7
Pixelfan
Registered User
 
Join Date: Apr 2012
Location: Germany
Posts: 12
Hi Toni,

Quote:
Originally Posted by Toni Wilen View Post
Note that shader code can be "stacked", previous code writes to temp buffer that next one reads and so on.. (RGB mask or current scanline is already separate pass on top of selected filter)
Can you quote a simple example of shader code, e.g. for 2x scaling with linear interpolation? I would like to get a better impression of how it works.

Does it iterate through the pixels of the output image? Can it access arbitrary pixels of the input image?

Best regards,
Pixelfan
Pixelfan is offline  
Old 25 April 2012, 19:11   #8
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,505
Check existing shader code (package available from winuae.net). I am not 100% sure how they work either

It can access any source pixel (but method isn't very intuitive in my opinion). Destination pixels are not available without multiple passes.
Toni Wilen is offline  
Old 25 April 2012, 23:47   #9
Pixelfan
Registered User
 
Join Date: Apr 2012
Location: Germany
Posts: 12
I did some more refinements:

http://eab.abime.net/picture.php?alb...pictureid=2216

Here is the python code that I used to scale the image:

Code:
from PIL import Image
img = Image.open("turrican_input.png")
imgsize = img.size
outsize = (3*imgsize[0]-1, 3*imgsize[1])
out = Image.new('RGB', outsize)

for y in range(0, outsize[1]):
  for x in range(0, outsize[0]):
    (red,grn,blu) = img.getpixel((x/3,y/3))
    if x % 3 == 2:
      # every 3rd target pixel is horizontally interpolated
      next = img.getpixel((x/3+1,y/3))
      red = (red >> 1) + (next[0] >> 1)
      grn = (grn >> 1) + (next[1] >> 1)
      blu = (blu >> 1) + (next[2] >> 1)
    if y % 3 != 1:
      # each source line is represented by 3 target lines
      # only the 2nd target line has the original brightness
      # brightness of 1st and 3rd target line is adjusted
      brightest = max(red,grn,blu)
      red = (red * brightest) >> 8
      grn = (grn * brightest) >> 8
      blu = (blu * brightest) >> 8
    out.putpixel((x,y), (red,grn,blu))

out.save("turrican_output.png")
Here is a magnified section of the output image to give you a better impression of what the algorithm actually does:



Best regards,
Pixelfan

Last edited by Pixelfan; 26 April 2012 at 10:30.
Pixelfan is offline  
Old 27 April 2012, 12:36   #10
Pixelfan
Registered User
 
Join Date: Apr 2012
Location: Germany
Posts: 12
I have refined my scanline filter further more such that it will keep the original brightness impression of the original image.

Here is a comparison of an 3x scaled image without any filtering and after applying my scanline filter (which also does some horizontal interpolation):



I think now it comes very close to what the games looked like on my CRT monitor.
Pixelfan is offline  
Old 27 April 2012, 14:20   #11
viddi
Moderator
 
viddi's Avatar
 
Join Date: Apr 2006
Location: Germany
Age: 44
Posts: 4,007
Great work, Mr. Pixel!
viddi is offline  
Old 27 April 2012, 21:20   #12
Pixelfan
Registered User
 
Join Date: Apr 2012
Location: Germany
Posts: 12
Quote:
Originally Posted by viddi View Post
Great work, Mr. Pixel!
Thank you.

I am trying to understand the shader programming language in order to use this with WinUAE.
Pixelfan is offline  
Old 29 April 2012, 21:43   #13
Pixelfan
Registered User
 
Join Date: Apr 2012
Location: Germany
Posts: 12
Hi Toni,

Quote:
Originally Posted by Toni Wilen View Post
Only way to do it dynamically is to create pixel shader scanline "filter".
I played a bit around with the D3D filters and tried to create one of my own.

Unfortunately, I am unable to separate lines cleanly as needed for the scanline effect. Even the 2xSaI+Scanlines which is delivered in your filter package looks totally weird:



What settings are required to get the 2xSaI+Scanlines filter working correctly?

Best regards,
Pixelfan
Pixelfan is offline  
Old 29 April 2012, 22:03   #14
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,505
Quote:
Originally Posted by Pixelfan View Post
What settings are required to get the 2xSaI+Scanlines filter working correctly?
Not sure if this fixed it but make sure you use 2.4.1 betas (or 2.3.3), 2.4.0 uses wrong size for internal filter texture.
Toni Wilen is offline  
Old 29 April 2012, 22:12   #15
Pixelfan
Registered User
 
Join Date: Apr 2012
Location: Germany
Posts: 12
Hi Toni,

thanks for your reply. However, I am already using Public Beta Beta 9, 2012.04.22.

Should I switch back to 2.3.3?

Something else: What is the intended size of the internal filter texture? Does it depend on the "horiz. size" and "vert. size" settings in the filter tab?

Best regards,
Pixelfan

Last edited by Pixelfan; 29 April 2012 at 22:18.
Pixelfan is offline  
Old 30 April 2012, 00:01   #16
Pixelfan
Registered User
 
Join Date: Apr 2012
Location: Germany
Posts: 12
Hi Toni,

This is really strange. In the D3D shader, I need to multiply the normalized vertical coordinate with 577 in order to get the correct unnormalized line number.

As normalized coordinates reach from 0.0 to 1.0, this would correspond to unnormalized line numbers 0 to 577 which makes a total of 578 lines. However, I thought that the maximum vertical resolution of the OCS was 576.

Furthermore, if I set the horiz. size and vert. size to 3x in the filter tab, I would have expected that the line number in the D3D shader increases to something between 864 an 866. However, none of these multipliers result in clean scanline. Thus, the number of lines seems to be something else.

By the way: why is there no preselector for 3x size in the filter tab?

Best regards,
Pixelfan
Pixelfan is offline  
Old 30 April 2012, 01:08   #17
Pixelfan
Registered User
 
Join Date: Apr 2012
Location: Germany
Posts: 12
All,

I implemented a very simple D3D shader version of my non-linear scanline algorithm:

Code:
#include "shader.code"

float scaling : SCALING = 2.0;

// multiplicator to transform normalized Y coordinates to denormalized line numbers
float rs_numlines = 577.0;

// this controls the brightness correction
// use 1/2 if every 2nd line is a scanline
// use 1/3 if every 3rd line is a scanline
float rs_scanfrac = 0.5;

string name : NAME = "Retroscan";
string combineTechique : COMBINETECHNIQUE =  "Retroscan";

// **VS**

VERTEX_STUFF_W S_VERTEX (float3 p : POSITION, float2 tc : TEXCOORD0)
{
  VERTEX_STUFF_W OUT = (VERTEX_STUFF_W)0;

  OUT.coord = mul(float4(p,1),WorldViewProjection);
  OUT.CT = tc;

  return OUT;
}

// **PS**

float4 S_FRAGMENT ( in VERTEX_STUFF_W VAR ) : COLOR
{
  // extract the current pixel from the source texture
  float3 pixel = tex2D(s_p, VAR.CT ).xyz;

  // pre-calculate constant value that is used in the brightness calculation
  float rs_val = (1.0 - rs_scanfrac) / (2.0 * rs_scanfrac);

  // adjust the brightness for the pixels that are not part of a scanline
  pixel = sqrt(pixel / rs_scanfrac + rs_val * rs_val) - rs_val;

  // transform normalized Y coordinates to denormalized line numbers
  int rs_line = int(VAR.CT.y * rs_numlines);

  // only execute for scanlines
  if (rs_line % 2 == 1)
  {
    // decrease brightness for the pixels that are part of a scanline
    pixel = pixel * pixel;
  }

  return float4(pixel,0);
}

technique Retroscan
{
   pass P0
   {
     VertexShader = compile vs_3_0 S_VERTEX();
     PixelShader  = compile ps_3_0 S_FRAGMENT();
   }  
}
Unfortunately, it only gives clean results with the following settings:





I hope that Toni can get it working cleanly with other resolutions und fullscreen mode as well, because it looks really good from my point of view.

Once it works with other resolutions, I can also add some horizontal interpolation which I used in the pictures from my previous posts.

Best regards,
Pixelfan

Last edited by Pixelfan; 30 April 2012 at 10:50.
Pixelfan is offline  
Old 30 April 2012, 02:01   #18
bLAZER
Awesome to the max
 
bLAZER's Avatar
 
Join Date: Mar 2007
Location: Gothenburg / Sweden
Age: 47
Posts: 1,006
Good work, those scanlines look verrry nice.
bLAZER is offline  
Old 30 April 2012, 10:35   #19
Pixelfan
Registered User
 
Join Date: Apr 2012
Location: Germany
Posts: 12
Hi Toni,

I noticed that there are some filters which do not use D3D. For example, the hq3x filter.

How are these filters implemented?

Best regards,
Pixelfan
Pixelfan is offline  
Old 30 April 2012, 11:42   #20
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,505
Quote:
Originally Posted by Pixelfan View Post
I noticed that there are some filters which do not use D3D. For example, the hq3x filter.
They are built-in, pure software, very slow.

Quote:
Originally Posted by Pixelfan View Post
This is really strange. In the D3D shader, I need to multiply the normalized vertical coordinate with 577 in order to get the correct unnormalized line number.
use TEXELSIZE parameter, it contains 1.0/width and 1.0/height values.

Quote:
As normalized coordinates reach from 0.0 to 1.0, this would correspond to unnormalized line numbers 0 to 577 which makes a total of 578 lines. However, I thought that the maximum vertical resolution of the OCS was 576.
Probably some rounding. It is not guaranteed to be exact.

Quote:
Furthermore, if I set the horiz. size and vert. size to 3x in the filter tab, I would have expected that the line number in the D3D shader increases to something between 864 an 866. However, none of these multipliers result in clean scanline. Thus, the number of lines seems to be something else.
Use the 1x-4x setting next to filter select menu. It sets internal texture size multiplier.

Quote:
By the way: why is there no preselector for 3x size in the filter tab?
Because it isn't really needed. This option only scales the image, original texture is still the same. See above.
Toni Wilen is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
"Reminder "Lincs Amiga User Group aka "LAG" Meet Sat 5th of January 2013" rockape News 4 30 January 2013 00:06
Shadow of the third moon - crashes on "Disk" option PopoCop support.Games 7 26 December 2012 18:11
The "Match a500 speed" Option only works if CPU is set to Mc68000. Sp_ support.WinUAE 9 15 December 2008 17:36

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 15:35.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.28278 seconds with 15 queries