View Single Post
Old 05 January 2017, 10:04   #1
Registered User
rsn8887's Avatar
Join Date: Oct 2006
Location: USA
Posts: 726
WIP: Sharp_Bilinear_Simple filter (finally integer pre-scale!)

EDIT3: Another new version. Automatic integer prescale factor calculation is finally correct. Shader model reduced to v1.0 vertex, v2.0 pixel. This only works with latest winuae beta:

EDIT: New version. No need to adjust the prescalefactors anymore, it is done automatically now. The old version has been renamed to ""

NOTE: There's still a problem making the integer pre-scale not quite perfect. This is due to a NULL filter discrepancy issue. I have started a new thread. Once that is fixed, I will post another update.

Finally, after I got it to work for UAE4All2 on the Vita, I now managed to make a "sharp_bilinear_simple" filter for WinUAE that does what I have always hoped to have in WinUAE: a perfect largest possible integer pre-scale followed by the bilinear scaling of only the remainder.

This gives the best sharp pixels with minimum blurring, and no other artefacts even if your output size is not an integer multiple of the Amiga resolution.

A side effect of this is that there's no real need for using line doubling or superhires just to get sharp pixels. I turned mine off. Of course there might be other reasons to use those settings.

Attached here are
- the code in a box just for reference
- the zipped file to extract. The sharp_bilinear_simple.fx file should go in the plugins/filtershaders/direct3d folder
- Two example screenshots comparing my filter (sharp) to standard WinUAE bilinear scaling (blurry)
- A screenshot of the filter settings window. The bilinear setting being ON is important because of some amount of post scaling that happens.

Note: WinUAE is great and by far the best Amiga emulator out there, but the filter settings window must be the most confusing and obtuse part of the whole GUI. There are so many choices and numbers without labels

EDIT: Latest code shown using TARGETDIMS to find prescale factor automatically.
   Author: rsn8887 (based on TheMaister)
   License: Public domain
   Version 5
   This is an integer prescale filter that should be combined
   with a bilinear hardware filtering (GL_BILINEAR filter or some such) to achieve
   a smooth scaling result with minimum blur. This is good for pixelgraphics
   that are scaled by non-integer factors.
   Version 5: Fix broken prescale factor calculation (again)
   Version 4: Fix completely broken prescale factor calculation 
   Version 3: fix small shift and missing pixels
   Version 2: Automatic prescale factor	
   Version 1: First Release, manual prescale factor

float4x4 WorldViewProjection	: WORLDVIEWPROJECTION;

float2 sourceSize : SOURCEDIMS;
float2 targetSize : TARGETDIMS;

texture sourceTex 	: SOURCETEXTURE;

sampler	sourceSampler = sampler_state
	Texture   = (sourceTex);
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	AddressU  = Clamp;
	AddressV  = Clamp;

string combineTechnique : COMBINETECHNIQUE =  "Sharp_Bilinear_Simple";

struct VS_OUTPUT
	float4 oPosition 	: POSITION;
	float2 oTexCoord 	: TEXCOORD0;
	float2 texelScaled : TEXCOORD1;
	float2 prescaleFactor : TEXCOORD2;

// Vertex Shader
VS_OUTPUT vShader (float3 pos : POSITION, float2 texCoord : TEXCOORD0)

	OUT.oPosition = mul(float4(pos,1.0f),WorldViewProjection);
	OUT.oTexCoord = texCoord;
	//This fixes the missing pixels on the top of the screen in WinUAE
	OUT.texelScaled = (texCoord*sourceSize)-0.5f;
	//find optimum integer prescale and pass it to the pixelShader
	OUT.prescaleFactor = floor(targetSize/sourceSize);	

	return OUT;

// Pixel Shader
float4 pShader ( in VS_OUTPUT inp ) : COLOR
	//inp.texelScaled has already been multiplied by texture_size inside vertex shader
	float2 texelFloored = floor(inp.texelScaled);
	float2 s = frac(inp.texelScaled);

	float2 regionRange = 0.5f - 0.5f / inp.prescaleFactor;

	// Figure out where in the texel to sample to get correct pre-scaled bilinear.
	// Uses the hardware bilinear interpolator to avoid having to sample 4 times manually. 
	float2 centerDist = s - 0.5f;
	float2 f = (centerDist - clamp(centerDist, -regionRange, regionRange)) * inp.prescaleFactor + 0.5f;
	float2 modTexel = texelFloored + f;
	return float4(tex2D(sourceSampler, modTexel/sourceSize).rgb, 1.0f);   

technique Sharp_Bilinear_Simple
   pass P0
     VertexShader = compile vs_1_0 vShader();
     PixelShader  = compile ps_2_0 pShader();
Attached Thumbnails
Click image for larger version

Name:	Sharp_Bilinear_Simple_Settings.PNG
Views:	80
Size:	74.2 KB
ID:	51579   Click image for larger version

Name:	bilinear.jpg
Views:	143
Size:	211.4 KB
ID:	51580   Click image for larger version

Name:	sharp_bilinear_simple.jpg
Views:	136
Size:	242.8 KB
ID:	51581  
Attached Files
File Type: zip (1.8 KB, 15 views)

Last edited by rsn8887; 11 January 2017 at 23:10.
rsn8887 is offline  
AdSense AdSense  
Page generated in 0.05479 seconds with 10 queries