Quality and Performance improvements

- HLSL now uses NPOT sized target surfaces (breaks compatibility with
graphics cards based on R300/R400/NV30 and older)
- HLSL target surfaces now have the size of the screen canvas
- removed HLSL pre-scale factor
- HLSL now uses a sharp bilinear interpolation to pre-scale textures to
screen canvas size, based on [Themaister's] implementation
- improved overall performance (based on the previously required
pre-scale factor, you might notice a 5-50% speed-up depending on your
graphics card, more if you used a higher pre-scale factor)
- improved shadow mask quality (pixel-perfect) in screen-mode
- fixed half source texel offset of bloom level alignment
- removed ./hlsl/artwork_support folder
- all shaders after pre-scale are now based on screen coordinate
(workaground, till both raster and vector pass can work on texture
coordinates)
- disabled distortion shader for more than one screen and for artworks
in full mode, does not affect artworks in copped mode (workaground, till
both raster and vector pass can work on texture coordinates)
- moved compute_texture_size() from texture_info to texture_manager (nw)
This commit is contained in:
ImJezze 2016-02-20 21:58:56 +01:00
parent d15d53c728
commit e57c90084c
20 changed files with 381 additions and 1018 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

@ -8,8 +8,6 @@ yiq_enable 0/1 Enables YIQ-colorspace post-processing.
NTSC TV appearance on TV-based systems when configured NTSC TV appearance on TV-based systems when configured
properly. properly.
hlslpath [path] Path to the .fx files that are in use. (default: hlsl) hlslpath [path] Path to the .fx files that are in use. (default: hlsl)
hlsl_prescale_x [horizontal] HLSL pre-scale override factor for X. (0 for auto)
hlsl_prescale_y [vertical] HLSL pre-scale override factor for Y. (0 for auto)
hlsl_write [filename] Enables HLSL AVI writing. (huge disk bandwidth suggested) hlsl_write [filename] Enables HLSL AVI writing. (huge disk bandwidth suggested)
hlsl_snap_width [width] HLSL upscaled-snapshot width. (default: 2048) hlsl_snap_width [width] HLSL upscaled-snapshot width. (default: 2048)
hlsl_snap_height [height] HLSL upscaled-snapshot height. (default: 1536) hlsl_snap_height [height] HLSL upscaled-snapshot height. (default: 1536)

View File

@ -1,101 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:ImJezze
//-----------------------------------------------------------------------------
// Distortion Effect
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Sampler Definitions
//-----------------------------------------------------------------------------
texture DiffuseTexture;
sampler DiffuseSampler = sampler_state
{
Texture = <DiffuseTexture>;
MipFilter = LINEAR;
MinFilter = LINEAR;
MagFilter = LINEAR;
AddressU = CLAMP;
AddressV = CLAMP;
AddressW = CLAMP;
};
//-----------------------------------------------------------------------------
// Vertex Definitions
//-----------------------------------------------------------------------------
struct VS_INPUT
{
float4 Position : POSITION;
float4 Color : COLOR0;
float2 TexCoord : TEXCOORD0;
};
struct VS_OUTPUT
{
float4 Position : POSITION;
float4 Color : COLOR0;
float2 TexCoord : TEXCOORD0;
};
struct PS_INPUT
{
float4 Color : COLOR0;
float2 TexCoord : TEXCOORD0;
};
//-----------------------------------------------------------------------------
// Distortion Vertex Shader
//-----------------------------------------------------------------------------
uniform float2 ScreenDims; // size of the window or fullscreen
uniform float2 TargetDims;
VS_OUTPUT vs_main(VS_INPUT Input)
{
VS_OUTPUT Output = (VS_OUTPUT)0;
Output.Position = float4(Input.Position.xyz, 1.0f);
Output.Position.xy /= ScreenDims;
Output.Position.y = 1.0f - Output.Position.y; // flip y
Output.Position.xy -= 0.5f; // center
Output.Position.xy *= 2.0f; // zoom
Output.Color = Input.Color;
Output.TexCoord = Input.Position.xy / ScreenDims;
Output.TexCoord += 0.5f / TargetDims; // half texel offset correction (DX9)
return Output;
}
//-----------------------------------------------------------------------------
// Post-Processing Pixel Shader
//-----------------------------------------------------------------------------
float4 ps_main(PS_INPUT Input) : COLOR
{
float2 BaseCoord = Input.TexCoord;
// Color
float4 BaseColor = tex2D(DiffuseSampler, BaseCoord);
BaseColor.a = 1.0f;
return BaseColor;
}
//-----------------------------------------------------------------------------
// Distortion Effect
//-----------------------------------------------------------------------------
technique DefaultTechnique
{
pass Pass0
{
Lighting = FALSE;
VertexShader = compile vs_3_0 vs_main();
PixelShader = compile ps_3_0 ps_main();
}
}

View File

@ -1,541 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz,ImJezze
//-----------------------------------------------------------------------------
// Scanline, Shadowmask & Distortion Effect
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Sampler Definitions
//-----------------------------------------------------------------------------
texture DiffuseTexture;
sampler DiffuseSampler = sampler_state
{
Texture = <DiffuseTexture>;
MipFilter = LINEAR;
MinFilter = LINEAR;
MagFilter = LINEAR;
AddressU = CLAMP;
AddressV = CLAMP;
AddressW = CLAMP;
};
texture ShadowTexture;
sampler ShadowSampler = sampler_state
{
Texture = <ShadowTexture>;
MipFilter = LINEAR;
MinFilter = LINEAR;
MagFilter = LINEAR;
AddressU = WRAP;
AddressV = WRAP;
AddressW = WRAP;
};
//-----------------------------------------------------------------------------
// Vertex Definitions
//-----------------------------------------------------------------------------
struct VS_INPUT
{
float4 Position : POSITION;
float4 Color : COLOR0;
float2 TexCoord : TEXCOORD0;
};
struct VS_OUTPUT
{
float4 Position : POSITION;
float4 Color : COLOR0;
float2 TexCoord : TEXCOORD0;
float2 ScreenCoord : TEXCOORD1;
};
struct PS_INPUT
{
float4 Color : COLOR0;
float2 TexCoord : TEXCOORD0;
float2 ScreenCoord : TEXCOORD1;
};
//-----------------------------------------------------------------------------
// Constants
//-----------------------------------------------------------------------------
static const float Epsilon = 1.0e-7f;
static const float PI = 3.1415927f;
static const float PHI = 1.618034f;
static const float E = 2.7182817f;
static const float Gelfond = 23.140692f; // e^pi (Gelfond constant)
static const float GelfondSchneider = 2.6651442f; // 2^sqrt(2) (Gelfond-Schneider constant)
//-----------------------------------------------------------------------------
// Functions
//-----------------------------------------------------------------------------
// www.stackoverflow.com/questions/5149544/can-i-generate-a-random-number-inside-a-pixel-shader/
float random(float2 seed)
{
// irrationals for pseudo randomness
float2 i = float2(Gelfond, GelfondSchneider);
return frac(cos(dot(seed, i)) * 123456.0f);
}
// www.dinodini.wordpress.com/2010/04/05/normalized-tunable-sigmoid-functions/
float normalizedSigmoid(float n, float k)
{
// valid for n and k in range of -1.0 and 1.0
return (n - n * k) / (k - abs(n) * 2.0f * k + 1);
}
// www.iquilezles.org/www/articles/distfunctions/distfunctions.htm
float roundBox(float2 p, float2 b, float r)
{
return length(max(abs(p) - b + r, 0.0f)) - r;
}
//-----------------------------------------------------------------------------
// Scanline, Shadowmask & Distortion Vertex Shader
//-----------------------------------------------------------------------------
uniform float2 ScreenDims; // size of the window or fullscreen
uniform float2 SourceDims; // size of the texture in power-of-two size
uniform float2 SourceRect; // size of the uv rectangle
uniform float2 TargetDims; // size of the target surface
uniform float2 QuadDims; // size of the screen quad
uniform float2 ShadowDims = float2(32.0f, 32.0f); // size of the shadow texture (extended to power-of-two size)
uniform float2 ShadowUVOffset = float2(0.0f, 0.0f);
uniform bool SwapXY = false;
uniform int RotationType = 0; // 0 = 0°, 1 = 90°, 2 = 180°, 3 = 270°
uniform bool PrepareBloom = false; // disables some effects for rendering bloom textures
uniform bool PrepareVector = false;
VS_OUTPUT vs_main(VS_INPUT Input)
{
VS_OUTPUT Output = (VS_OUTPUT)0;
float2 shadowUVOffset = ShadowUVOffset;
shadowUVOffset = SwapXY
? shadowUVOffset.yx
: shadowUVOffset.xy;
float2 ScreenCoordOffset = 0.0f;
ScreenCoordOffset += shadowUVOffset;
Output.ScreenCoord = Input.Position.xy;
Output.ScreenCoord += ScreenCoordOffset;
Output.Position = float4(Input.Position.xyz, 1.0f);
Output.Position.xy /= ScreenDims;
Output.Position.y = 1.0f - Output.Position.y; // flip y
Output.Position.xy -= 0.5f; // center
Output.Position.xy *= 2.0f; // zoom
Output.TexCoord = PrepareVector
? Input.Position.xy / ScreenDims
: Input.TexCoord;
Output.TexCoord += 0.5f / TargetDims; // half texel offset correction (DX9)
Output.Color = Input.Color;
return Output;
}
//-----------------------------------------------------------------------------
// Scanline, Shadowmask & Distortion Pixel Shader
//-----------------------------------------------------------------------------
uniform float HumBarDesync = 60.0f / 59.94f - 1.0f; // difference between the 59.94 Hz field rate and 60 Hz line frequency (NTSC)
uniform float HumBarAlpha = 0.0f;
uniform float TimeMilliseconds = 0.0f;
uniform float2 ScreenScale = float2(1.0f, 1.0f);
uniform float2 ScreenOffset = float2(0.0f, 0.0f);
uniform float ScanlineAlpha = 1.0f;
uniform float ScanlineScale = 1.0f;
uniform float ScanlineBrightScale = 1.0f;
uniform float ScanlineBrightOffset = 1.0f;
uniform float ScanlineOffset = 1.0f;
uniform float ScanlineHeight = 1.0f;
uniform float3 BackColor = float3(0.0f, 0.0f, 0.0f);
uniform float CurvatureAmount = 1.0f;
uniform float RoundCornerAmount = 0.0f;
uniform float SmoothBorderAmount = 0.0f;
uniform float VignettingAmount = 0.0f;
uniform float ReflectionAmount = 0.0f;
uniform int ShadowTileMode = 0; // 0 based on screen dimension, 1 based on source dimension
uniform float ShadowAlpha = 0.0f;
uniform float2 ShadowCount = float2(6.0f, 6.0f);
uniform float2 ShadowUV = float2(0.25f, 0.25f);
uniform float3 Power = float3(1.0f, 1.0f, 1.0f);
uniform float3 Floor = float3(0.0f, 0.0f, 0.0f);
float2 GetRatioCorrection()
{
if (PrepareVector)
{
float ScreenRatio = ScreenDims.x / ScreenDims.y;
float QuadRatio = QuadDims.x / QuadDims.y;
float ScreenQuadRatio = QuadRatio / ScreenRatio;
return ScreenQuadRatio > 1.0f
? float2(1.0, 1.0f / ScreenQuadRatio)
: float2(ScreenQuadRatio, 1.0);
}
else
{
return SourceRect;
}
}
float GetNoiseFactor(float n, float random)
{
// smaller n become more noisy
return 1.0f + random * max(0.0f, 0.25f * pow(E, -8 * n));
}
float GetVignetteFactor(float2 coord, float amount)
{
float2 VignetteCoord = coord;
float VignetteLength = length(VignetteCoord);
float VignetteBlur = (amount * 0.75f) + 0.25;
// 0.5 full screen fitting circle
float VignetteRadius = 1.0f - (amount * 0.25f);
float Vignette = smoothstep(VignetteRadius, VignetteRadius - VignetteBlur, VignetteLength);
return saturate(Vignette);
}
float GetSpotAddend(float2 coord, float amount)
{
float2 RatioCorrection = GetRatioCorrection();
// normalized screen canvas ratio
float2 CanvasRatio = PrepareVector
? float2(1.0f, QuadDims.y / QuadDims.x)
: float2(1.0f, SwapXY
? QuadDims.x / QuadDims.y
: QuadDims.y / QuadDims.x);
// upper right quadrant
float2 spotOffset = PrepareVector
? RotationType == 1 // 90°
? float2(-0.25f, -0.25f)
: RotationType == 2 // 180°
? float2(0.25f, -0.25f)
: RotationType == 3 // 270°
? float2(0.25f, 0.25f)
: float2(-0.25f, 0.25f)
: SwapXY
? float2(0.25f, 0.25f)
: float2(-0.25f, 0.25f);
float2 SpotCoord = coord;
SpotCoord += spotOffset * RatioCorrection;
SpotCoord *= CanvasRatio;
SpotCoord /= RatioCorrection;
float SpotBlur = amount;
// 0.5 full screen fitting circle
float SpotRadius = amount * 0.75f;
float Spot = smoothstep(SpotRadius, SpotRadius - SpotBlur, length(SpotCoord));
float SigmoidSpot = amount * normalizedSigmoid(Spot, 0.75);
// increase strength by 100%
SigmoidSpot = SigmoidSpot * 2.0f;
return saturate(SigmoidSpot);
}
float GetRoundCornerFactor(float2 coord, float radiusAmount, float smoothAmount)
{
float2 RatioCorrection = GetRatioCorrection();
// reduce smooth amount down to radius amount
smoothAmount = min(smoothAmount, radiusAmount);
float2 CanvasDims = PrepareVector
? ScreenDims
: SwapXY
? QuadDims.yx / SourceRect
: QuadDims.xy / SourceRect;
coord = PrepareVector
? coord
: coord - 1.0f / SourceDims; // alignment correction (raster graphics)
float range = min(QuadDims.x, QuadDims.y) * 0.5;
float radius = range * max(radiusAmount, 0.0025f);
float smooth = 1.0 / (range * max(smoothAmount, 0.0025f));
// compute box
float box = roundBox(CanvasDims * (coord * 2.0f), CanvasDims * RatioCorrection, radius);
// apply smooth
box *= smooth;
box += 1.0f - pow(smooth * 0.5f, 0.5f);
float border = smoothstep(1.0f, 0.0f, box);
return saturate(border);
}
// www.francois-tarlier.com/blog/cubic-lens-distortion-shader/
float2 GetDistortedCoords(float2 centerCoord, float amount)
{
// lens distortion coefficient
float k = amount;
// cubic distortion value
float kcube = amount * 2.0f;
// compute cubic distortion factor
float r2 = centerCoord.x * centerCoord.x + centerCoord.y * centerCoord.y;
float f = kcube == 0.0f
? 1.0f + r2 * k
: 1.0f + r2 * (k + kcube * sqrt(r2));
// fit screen bounds
f /= 1.0f + amount * 0.5f;
// apply cubic distortion factor
centerCoord *= f;
return centerCoord;
}
float2 GetCoords(float2 coord, float2 centerOffset, float distortionAmount)
{
float2 RatioCorrection = GetRatioCorrection();
// center coordinates
coord -= centerOffset;
// apply ratio difference between screen and quad
coord /= RatioCorrection;
// distort coordinates
coord = GetDistortedCoords(coord, distortionAmount);
// revert ratio difference between screen and quad
coord *= RatioCorrection;
// un-center coordinates
coord += centerOffset;
return coord;
}
float2 GetAdjustedCoords(float2 coord, float2 centerOffset, float distortionAmount)
{
float2 RatioCorrection = GetRatioCorrection();
// center coordinates
coord -= centerOffset;
// apply ratio difference between screen and quad
coord /= RatioCorrection;
// apply screen scale
coord /= ScreenScale;
// distort coordinates
coord = GetDistortedCoords(coord, distortionAmount);
// revert ratio difference between screen and quad
coord *= RatioCorrection;
// un-center coordinates
coord += centerOffset;
// apply screen offset
coord += (centerOffset * 2.0) * ScreenOffset;
return coord;
}
float4 ps_main(PS_INPUT Input) : COLOR
{
float2 ScreenTexelDims = 1.0f / ScreenDims;
float2 SourceTexelDims = 1.0f / SourceDims;
float2 HalfSourceRect = SourceRect * 0.5f;
float2 ScreenCoord = Input.ScreenCoord / ScreenDims;
ScreenCoord = GetCoords(ScreenCoord, float2(0.5f, 0.5f), CurvatureAmount * 0.25f); // reduced amount
float2 DistortionCoord = Input.TexCoord;
DistortionCoord = GetCoords(DistortionCoord, HalfSourceRect, CurvatureAmount * 0.25f); // reduced amount
float2 BaseCoord = Input.TexCoord;
BaseCoord = GetAdjustedCoords(BaseCoord, HalfSourceRect, CurvatureAmount * 0.25f); // reduced amount
float2 DistortionCoordCentered = DistortionCoord;
DistortionCoordCentered -= HalfSourceRect;
float2 BaseCoordCentered = BaseCoord;
BaseCoordCentered -= HalfSourceRect;
float4 BaseColor = tex2D(DiffuseSampler, BaseCoord);
BaseColor.a = 1.0f;
if (BaseCoord.x < 0.0f || BaseCoord.y < 0.0f)
{
BaseColor.rgb = 0.0f;
}
// Mask Simulation (may not affect bloom)
if (!PrepareBloom && ShadowAlpha > 0.0f)
{
float2 shadowDims = ShadowDims;
shadowDims = SwapXY
? shadowDims.yx
: shadowDims.xy;
float2 shadowUV = ShadowUV;
// shadowUV = SwapXY
// ? shadowUV.yx
// : shadowUV.xy;
float2 screenCoord = ShadowTileMode == 0 ? ScreenCoord : BaseCoord;
screenCoord = SwapXY
? screenCoord.yx
: screenCoord.xy;
float2 shadowCount = ShadowCount;
shadowCount = SwapXY
? shadowCount.yx
: shadowCount.xy;
float2 shadowTile = ((ShadowTileMode == 0 ? ScreenTexelDims : SourceTexelDims) * shadowCount);
shadowTile = SwapXY
? shadowTile.yx
: shadowTile.xy;
float2 ShadowFrac = frac(screenCoord / shadowTile);
float2 ShadowCoord = (ShadowFrac * shadowUV);
ShadowCoord += 0.5f / shadowDims; // half texel offset
// ShadowCoord = SwapXY
// ? ShadowCoord.yx
// : ShadowCoord.xy;
float4 ShadowColor = tex2D(ShadowSampler, ShadowCoord);
float3 ShadowMaskColor = lerp(1.0f, ShadowColor.rgb, ShadowAlpha);
float ShadowMaskClear = (1.0f - ShadowColor.a) * ShadowAlpha;
// apply shadow mask color
BaseColor.rgb *= ShadowMaskColor;
// clear shadow mask by background color
BaseColor.rgb = lerp(BaseColor.rgb, BackColor, ShadowMaskClear);
}
// Color Compression (may not affect bloom)
if (!PrepareBloom)
{
// increasing the floor of the signal without affecting the ceiling
BaseColor.rgb = Floor + (1.0f - Floor) * BaseColor.rgb;
}
// Color Power (may affect bloom)
BaseColor.r = pow(BaseColor.r, Power.r);
BaseColor.g = pow(BaseColor.g, Power.g);
BaseColor.b = pow(BaseColor.b, Power.b);
// Scanline Simulation (may not affect bloom)
if (!PrepareBloom)
{
// Scanline Simulation (may not affect vector screen)
if (!PrepareVector && ScanlineAlpha > 0.0f)
{
float BrightnessOffset = (ScanlineBrightOffset * ScanlineAlpha);
float BrightnessScale = (ScanlineBrightScale * ScanlineAlpha) + (1.0f - ScanlineAlpha);
float ColorBrightness = 0.299f * BaseColor.r + 0.587f * BaseColor.g + 0.114 * BaseColor.b;
float ScanlineCoord = BaseCoord.y * SourceDims.y * ScanlineScale * PI;
float ScanlineCoordJitter = ScanlineOffset * PHI;
float ScanlineSine = sin(ScanlineCoord + ScanlineCoordJitter);
float ScanlineWide = ScanlineHeight + max(1.0f, ScanlineHeight) * (1.0f - ColorBrightness);
float ScanlineAmount = pow(ScanlineSine * ScanlineSine, ScanlineWide);
float ScanlineBrightness = ScanlineAmount * BrightnessScale + BrightnessOffset * BrightnessScale;
BaseColor.rgb *= lerp(1.0f, ScanlineBrightness, ScanlineAlpha);
}
// Hum Bar Simulation (may not affect vector screen)
if (!PrepareVector && HumBarAlpha > 0.0f)
{
float HumBarStep = frac(TimeMilliseconds * HumBarDesync);
float HumBarBrightness = 1.0 - frac(BaseCoord.y / SourceRect.y + HumBarStep) * HumBarAlpha;
BaseColor.rgb *= HumBarBrightness;
}
}
// Output
float4 Output = PrepareVector
? BaseColor * (Input.Color + float4(1.0f, 1.0f, 1.0f, 0.0f))
: BaseColor * Input.Color;
Output.a = 1.0f;
// Vignetting Simulation (may not affect bloom)
if (!PrepareBloom)
{
float2 VignetteCoord = DistortionCoordCentered;
float VignetteFactor = GetVignetteFactor(VignetteCoord, VignettingAmount);
Output.rgb *= VignetteFactor;
}
// Light Reflection Simulation (may not affect bloom)
if (!PrepareBloom)
{
float3 LightColor = float3(1.0f, 0.90f, 0.80f);
float2 SpotCoord = DistortionCoordCentered;
float2 NoiseCoord = DistortionCoordCentered;
float SpotAddend = GetSpotAddend(SpotCoord, ReflectionAmount);
float NoiseFactor = GetNoiseFactor(SpotAddend, random(NoiseCoord));
Output.rgb += SpotAddend * NoiseFactor * LightColor;
}
// Round Corners Simulation (may affect bloom)
float2 RoundCornerCoord = DistortionCoordCentered;
float roundCornerFactor = GetRoundCornerFactor(RoundCornerCoord, RoundCornerAmount, SmoothBorderAmount);
Output.rgb *= roundCornerFactor;
return Output;
}
//-----------------------------------------------------------------------------
// Scanline & Shadowmask Effect
//-----------------------------------------------------------------------------
technique DefaultTechnique
{
pass Pass0
{
Lighting = FALSE;
VertexShader = compile vs_3_0 vs_main();
PixelShader = compile ps_3_0 ps_main();
}
}

View File

@ -68,48 +68,47 @@ VS_OUTPUT vs_main(VS_INPUT Input)
{ {
VS_OUTPUT Output = (VS_OUTPUT)0; VS_OUTPUT Output = (VS_OUTPUT)0;
float2 HalfSourceRect = SourceRect * 0.5f;
float2 QuadRatio =
float2(1.0f, SwapXY
? QuadDims.y / QuadDims.x
: QuadDims.x / QuadDims.y);
// imaginary texel dimensions independed from quad dimensions, but dependend on quad ratio
float2 FixedTexelDims = (1.0f / 1024.0) * SourceRect * QuadRatio;
Output.Position = float4(Input.Position.xyz, 1.0f); Output.Position = float4(Input.Position.xyz, 1.0f);
Output.Position.xy /= ScreenDims; Output.Position.xy /= ScreenDims;
Output.Position.y = 1.0f - Output.Position.y; // flip y Output.Position.y = 1.0f - Output.Position.y; // flip y
Output.Position.xy -= 0.5f; // center Output.Position.xy -= 0.5f; // center
Output.Position.xy *= 2.0f; // toom Output.Position.xy *= 2.0f; // toom
float2 TexCoord = Input.TexCoord; float2 TexCoord = Input.Position.xy / ScreenDims;
TexCoord += 0.5f / TargetDims; // half texel offset correction (DX9) TexCoord += 0.5f / TargetDims; // half texel offset correction (DX9)
Output.Color = Input.Color; // we have to handle the swap of the coordinates ourself, because we are using screen not texture coordinates
float3 convergeX = SwapXY ? ConvergeY : ConvergeX;
float3 convergeY = SwapXY ? ConvergeX : ConvergeY;
float3 radialConvergeX = SwapXY ? RadialConvergeY : RadialConvergeX;
float3 radialConvergeY = SwapXY ? RadialConvergeX : RadialConvergeY;
// imaginary texel dimensions independed from screen dimension, but ratio
float2 TexelDims = (1.0f / 1024) * (QuadDims / ScreenDims);
Output.TexCoordX = TexCoord.xxx; Output.TexCoordX = TexCoord.xxx;
Output.TexCoordY = TexCoord.yyy; Output.TexCoordY = TexCoord.yyy;
// center coordinates // center coordinates
Output.TexCoordX -= HalfSourceRect.xxx; Output.TexCoordX -= 0.5f * SourceRect.xxx;
Output.TexCoordY -= HalfSourceRect.yyy; Output.TexCoordY -= 0.5f * SourceRect.yyy;
// radial converge offset to "translate" the most outer pixel as thay would be translated by the linar converge with the same amount // radial converge offset to "translate" the most outer pixel as thay would be translated by the linar converge with the same amount
float2 radialConvergeOffset = 2.0f / SourceRect; float2 radialConvergeOffset = 2.0f / SourceRect;
// radial converge // radial converge
Output.TexCoordX *= 1.0f + RadialConvergeX * FixedTexelDims.xxx * radialConvergeOffset.xxx; Output.TexCoordX *= 1.0f + radialConvergeX * TexelDims.xxx * radialConvergeOffset.xxx;
Output.TexCoordY *= 1.0f + RadialConvergeY * FixedTexelDims.yyy * radialConvergeOffset.yyy; Output.TexCoordY *= 1.0f + radialConvergeY * TexelDims.yyy * radialConvergeOffset.yyy;
// un-center coordinates // un-center coordinates
Output.TexCoordX += HalfSourceRect.xxx; Output.TexCoordX += 0.5f * SourceRect.xxx;
Output.TexCoordY += HalfSourceRect.yyy; Output.TexCoordY += 0.5f * SourceRect.yyy;
// linear converge // linear converge
Output.TexCoordX += ConvergeX * FixedTexelDims.xxx; Output.TexCoordX += convergeX * TexelDims.xxx;
Output.TexCoordY += ConvergeY * FixedTexelDims.yyy; Output.TexCoordY += convergeY * TexelDims.yyy;
Output.Color = Input.Color;
return Output; return Output;
} }

View File

@ -119,7 +119,7 @@ uniform float ReflectionAmount = 0.0f;
uniform int RotationType = 0; // 0 = 0°, 1 = 90°, 2 = 180°, 3 = 270° uniform int RotationType = 0; // 0 = 0°, 1 = 90°, 2 = 180°, 3 = 270°
float2 GetRatioCorrection() float2 GetScreenQuadRatio()
{ {
float ScreenRatio = ScreenDims.x / ScreenDims.y; float ScreenRatio = ScreenDims.x / ScreenDims.y;
float QuadRatio = QuadDims.x / QuadDims.y; float QuadRatio = QuadDims.x / QuadDims.y;
@ -130,6 +130,15 @@ float2 GetRatioCorrection()
: float2(ScreenQuadRatio, 1.0); : float2(ScreenQuadRatio, 1.0);
} }
float2 GetQuadRatio()
{
float QuadRatio = QuadDims.x / QuadDims.y;
return QuadRatio > 1.0f
? float2 (1.0f, 1.0f / QuadRatio)
: float2 (QuadRatio, 1.0f);
}
float GetNoiseFactor(float3 n, float random) float GetNoiseFactor(float3 n, float random)
{ {
// smaller n become more noisy // smaller n become more noisy
@ -138,7 +147,7 @@ float GetNoiseFactor(float3 n, float random)
float GetVignetteFactor(float2 coord, float amount) float GetVignetteFactor(float2 coord, float amount)
{ {
float2 VignetteCoord = coord; float2 VignetteCoord = coord / (QuadDims / ScreenDims);
float VignetteLength = length(VignetteCoord); float VignetteLength = length(VignetteCoord);
float VignetteBlur = (amount * 0.75f) + 0.25; float VignetteBlur = (amount * 0.75f) + 0.25;
@ -152,10 +161,7 @@ float GetVignetteFactor(float2 coord, float amount)
float GetSpotAddend(float2 coord, float amount) float GetSpotAddend(float2 coord, float amount)
{ {
float2 RatioCorrection = GetRatioCorrection(); float2 QuadRatio = GetQuadRatio();
// normalized screen quad ratio
float2 QuadRatio = float2 (1.0f, QuadDims.y / QuadDims.x);
// upper right quadrant // upper right quadrant
float2 spotOffset = float2 spotOffset =
@ -167,10 +173,9 @@ float GetSpotAddend(float2 coord, float amount)
? float2(0.25f, 0.25f) ? float2(0.25f, 0.25f)
: float2(-0.25f, 0.25f); : float2(-0.25f, 0.25f);
float2 SpotCoord = coord; float2 SpotCoord = coord / (QuadDims / ScreenDims);
SpotCoord += spotOffset * RatioCorrection; SpotCoord += spotOffset * QuadRatio;
SpotCoord *= QuadRatio; SpotCoord *= QuadRatio;
SpotCoord /= RatioCorrection;
float SpotBlur = amount; float SpotBlur = amount;
@ -188,7 +193,7 @@ float GetSpotAddend(float2 coord, float amount)
float GetRoundCornerFactor(float2 coord, float radiusAmount, float smoothAmount) float GetRoundCornerFactor(float2 coord, float radiusAmount, float smoothAmount)
{ {
float2 RatioCorrection = GetRatioCorrection(); float2 ScreenQuadRatio = GetScreenQuadRatio();
// reduce smooth amount down to radius amount // reduce smooth amount down to radius amount
smoothAmount = min(smoothAmount, radiusAmount); smoothAmount = min(smoothAmount, radiusAmount);
@ -198,7 +203,7 @@ float GetRoundCornerFactor(float2 coord, float radiusAmount, float smoothAmount)
float smooth = 1.0 / (range * max(smoothAmount, 0.0025f)); float smooth = 1.0 / (range * max(smoothAmount, 0.0025f));
// compute box // compute box
float box = roundBox(ScreenDims * (coord * 2.0f), ScreenDims * RatioCorrection, radius); float box = roundBox(ScreenDims * (coord * 2.0f), ScreenDims * ScreenQuadRatio, radius);
// apply smooth // apply smooth
box *= smooth; box *= smooth;
@ -235,19 +240,19 @@ float2 GetDistortedCoords(float2 centerCoord, float amount)
float2 GetCoords(float2 coord, float distortionAmount) float2 GetCoords(float2 coord, float distortionAmount)
{ {
float2 RatioCorrection = GetRatioCorrection(); float2 ScreenQuadRatio = GetScreenQuadRatio();
// center coordinates // center coordinates
coord -= 0.5f; coord -= 0.5f;
// apply ratio difference between screen and quad // apply ratio difference between screen and quad
coord /= RatioCorrection; coord /= ScreenQuadRatio;
// distort coordinates // distort coordinates
coord = GetDistortedCoords(coord, distortionAmount); coord = GetDistortedCoords(coord, distortionAmount);
// revert ratio difference between screen and quad // revert ratio difference between screen and quad
coord *= RatioCorrection; coord *= ScreenQuadRatio;
// un-center coordinates // un-center coordinates
coord += 0.5f; coord += 0.5f;
@ -257,21 +262,18 @@ float2 GetCoords(float2 coord, float distortionAmount)
float4 ps_main(PS_INPUT Input) : COLOR float4 ps_main(PS_INPUT Input) : COLOR
{ {
float2 TexCoord = Input.TexCoord;
float2 BaseCoord = TexCoord;
// Screen Curvature // Screen Curvature
BaseCoord = GetCoords(BaseCoord, CurvatureAmount * 0.25f); // reduced amount float2 TexCoord = GetCoords(Input.TexCoord, CurvatureAmount * 0.25f); // reduced amount
float2 BaseCoordCentered = BaseCoord; float2 TexCoordCentered = TexCoord;
BaseCoordCentered -= 0.5f; TexCoordCentered -= 0.5f;
// Color // Color
float4 BaseColor = tex2D(DiffuseSampler, BaseCoord); float4 BaseColor = tex2D(DiffuseSampler, TexCoord);
BaseColor.a = 1.0f; BaseColor.a = 1.0f;
// Vignetting Simulation // Vignetting Simulation
float2 VignetteCoord = BaseCoordCentered; float2 VignetteCoord = TexCoordCentered;
float VignetteFactor = GetVignetteFactor(VignetteCoord, VignettingAmount); float VignetteFactor = GetVignetteFactor(VignetteCoord, VignettingAmount);
BaseColor.rgb *= VignetteFactor; BaseColor.rgb *= VignetteFactor;
@ -279,15 +281,15 @@ float4 ps_main(PS_INPUT Input) : COLOR
// Light Reflection Simulation // Light Reflection Simulation
float3 LightColor = float3(1.0f, 0.90f, 0.80f); // color temperature 5.000 Kelvin float3 LightColor = float3(1.0f, 0.90f, 0.80f); // color temperature 5.000 Kelvin
float2 SpotCoord = BaseCoordCentered; float2 SpotCoord = TexCoordCentered;
float2 NoiseCoord = BaseCoordCentered; float2 NoiseCoord = TexCoordCentered;
float SpotAddend = GetSpotAddend(SpotCoord, ReflectionAmount); float SpotAddend = GetSpotAddend(SpotCoord, ReflectionAmount);
float NoiseFactor = GetNoiseFactor(SpotAddend, random(NoiseCoord)); float NoiseFactor = GetNoiseFactor(SpotAddend, random(NoiseCoord));
BaseColor.rgb += SpotAddend * NoiseFactor * LightColor; BaseColor.rgb += SpotAddend * NoiseFactor * LightColor;
// Round Corners Simulation // Round Corners Simulation
float2 RoundCornerCoord = BaseCoordCentered; float2 RoundCornerCoord = TexCoordCentered;
float roundCornerFactor = GetRoundCornerFactor(RoundCornerCoord, RoundCornerAmount, SmoothBorderAmount); float roundCornerFactor = GetRoundCornerFactor(RoundCornerCoord, RoundCornerAmount, SmoothBorderAmount);
BaseColor.rgb *= roundCornerFactor; BaseColor.rgb *= roundCornerFactor;

View File

@ -53,9 +53,11 @@ struct PS_INPUT
uniform float2 ScreenDims; uniform float2 ScreenDims;
uniform float2 TargetDims; uniform float2 TargetDims;
uniform float2 SourceDims;
uniform float2 SourceRect; uniform float2 SourceRect;
uniform float2 QuadDims;
uniform bool PrepareVector; uniform bool VectorScreen;
static const float2 Coord0Offset = float2(-0.5f, -0.5f); static const float2 Coord0Offset = float2(-0.5f, -0.5f);
static const float2 Coord1Offset = float2( 0.5f, -0.5f); static const float2 Coord1Offset = float2( 0.5f, -0.5f);
@ -67,6 +69,8 @@ VS_OUTPUT vs_main(VS_INPUT Input)
VS_OUTPUT Output = (VS_OUTPUT)0; VS_OUTPUT Output = (VS_OUTPUT)0;
float2 TargetTexelDims = 1.0f / TargetDims; float2 TargetTexelDims = 1.0f / TargetDims;
float2 ScreenTexelDims = 1.0f / ScreenDims;
float2 SourceTexelDims = 1.0f / SourceDims;
Output.Position = float4(Input.Position.xyz, 1.0f); Output.Position = float4(Input.Position.xyz, 1.0f);
Output.Position.xy /= ScreenDims; Output.Position.xy /= ScreenDims;
@ -79,6 +83,13 @@ VS_OUTPUT vs_main(VS_INPUT Input)
float2 TexCoord = Input.Position.xy / ScreenDims; float2 TexCoord = Input.Position.xy / ScreenDims;
TexCoord += 0.5f / TargetDims; // half texel offset correction (DX9) TexCoord += 0.5f / TargetDims; // half texel offset correction (DX9)
float2 VectorTexelOffset = ScreenTexelDims * -0.5;
float2 RasterTexelOffset = SourceTexelDims * (0.5f * SourceRect) * (1.0f - (QuadDims / ScreenDims));
TexCoord += VectorScreen
? VectorTexelOffset
: RasterTexelOffset;
Output.TexCoord01.xy = TexCoord + Coord0Offset * TargetTexelDims; Output.TexCoord01.xy = TexCoord + Coord0Offset * TargetTexelDims;
Output.TexCoord01.zw = TexCoord + Coord1Offset * TargetTexelDims; Output.TexCoord01.zw = TexCoord + Coord1Offset * TargetTexelDims;
Output.TexCoord23.xy = TexCoord + Coord2Offset * TargetTexelDims; Output.TexCoord23.xy = TexCoord + Coord2Offset * TargetTexelDims;

View File

@ -51,7 +51,6 @@ struct PS_INPUT
uniform float2 ScreenDims; uniform float2 ScreenDims;
uniform float2 TargetDims; uniform float2 TargetDims;
uniform float2 SourceRect;
uniform float2 QuadDims; uniform float2 QuadDims;
VS_OUTPUT vs_main(VS_INPUT Input) VS_OUTPUT vs_main(VS_INPUT Input)
@ -64,7 +63,7 @@ VS_OUTPUT vs_main(VS_INPUT Input)
Output.Position.xy -= 0.5f; // center Output.Position.xy -= 0.5f; // center
Output.Position.xy *= 2.0f; // zoom Output.Position.xy *= 2.0f; // zoom
float2 TexCoord = Input.TexCoord; float2 TexCoord = Input.Position.xy / ScreenDims;
TexCoord += 0.5f / TargetDims; // half texel offset correction (DX9) TexCoord += 0.5f / TargetDims; // half texel offset correction (DX9)
Output.TexCoord = TexCoord; Output.TexCoord = TexCoord;
@ -93,15 +92,13 @@ static const float2 Coord8Offset = float2( 1.00f, -0.25f);
float4 ps_main(PS_INPUT Input) : COLOR float4 ps_main(PS_INPUT Input) : COLOR
{ {
float2 QuadRatio = // we have to handle the swap of the coordinates ourself, because we are using screen not texture coordinates
float2(1.0f, SwapXY float2 defocus = SwapXY ? Defocus.yx : Defocus.xy;
? QuadDims.y / QuadDims.x
: QuadDims.x / QuadDims.y);
// imaginary texel dimensions independed from quad dimensions, but dependend on quad ratio // imaginary texel dimensions independed from screen dimension, but ratio
float2 TexelDims = (1.0f / 1024.0) * SourceRect * QuadRatio; float2 TexelDims = (1.0f / 1024) * (QuadDims / ScreenDims);
float2 DefocusTexelDims = Defocus * TexelDims; float2 DefocusTexelDims = defocus * TexelDims;
float4 d = tex2D(DiffuseSampler, Input.TexCoord); float4 d = tex2D(DiffuseSampler, Input.TexCoord);
float3 d1 = tex2D(DiffuseSampler, Input.TexCoord + Coord1Offset * DefocusTexelDims).rgb; float3 d1 = tex2D(DiffuseSampler, Input.TexCoord + Coord1Offset * DefocusTexelDims).rgb;

View File

@ -44,7 +44,7 @@ struct PS_INPUT
}; };
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// YIQ Decode Vertex Shader // YIQ Vertex Shader
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
uniform float2 ScreenDims; uniform float2 ScreenDims;

View File

@ -79,7 +79,7 @@ VS_OUTPUT vs_main(VS_INPUT Input)
Output.Position.xy -= 0.5f; // center Output.Position.xy -= 0.5f; // center
Output.Position.xy *= 2.0f; // zoom Output.Position.xy *= 2.0f; // zoom
Output.TexCoord = Input.TexCoord; Output.TexCoord = Input.Position.xy / ScreenDims;
Output.TexCoord += 0.5f / TargetDims; // half texel offset correction (DX9) Output.TexCoord += 0.5f / TargetDims; // half texel offset correction (DX9)
Output.PrevCoord = Output.TexCoord; Output.PrevCoord = Output.TexCoord;

View File

@ -49,15 +49,17 @@ struct VS_OUTPUT
{ {
float4 Position : POSITION; float4 Position : POSITION;
float4 Color : COLOR0; float4 Color : COLOR0;
float2 TexCoord : TEXCOORD0; float2 SourceCoord : TEXCOORD0;
float2 ScreenCoord : TEXCOORD1; float2 TexCoord : TEXCOORD1;
float2 ScreenCoord : TEXCOORD2;
}; };
struct PS_INPUT struct PS_INPUT
{ {
float4 Color : COLOR0; float4 Color : COLOR0;
float2 TexCoord : TEXCOORD0; float2 SourceCoord : TEXCOORD0;
float2 ScreenCoord : TEXCOORD1; float2 TexCoord : TEXCOORD1;
float2 ScreenCoord : TEXCOORD2;
}; };
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -82,34 +84,31 @@ uniform float2 ShadowUVOffset = float2(0.0f, 0.0f);
uniform bool SwapXY = false; uniform bool SwapXY = false;
uniform bool PrepareBloom = false; // disables some effects for rendering bloom textures uniform bool PrepareBloom = false; // disables some effects for rendering bloom textures
uniform bool PrepareVector = false; uniform bool VectorScreen = false;
VS_OUTPUT vs_main(VS_INPUT Input) VS_OUTPUT vs_main(VS_INPUT Input)
{ {
VS_OUTPUT Output = (VS_OUTPUT)0; VS_OUTPUT Output = (VS_OUTPUT)0;
float2 shadowUVOffset = ShadowUVOffset;
shadowUVOffset = SwapXY
? shadowUVOffset.yx
: shadowUVOffset.xy;
float2 ScreenCoordOffset = 0.0f;
ScreenCoordOffset += shadowUVOffset;
Output.ScreenCoord = Input.Position.xy;
Output.ScreenCoord += ScreenCoordOffset;
Output.Position = float4(Input.Position.xyz, 1.0f); Output.Position = float4(Input.Position.xyz, 1.0f);
Output.Position.xy /= ScreenDims; Output.Position.xy /= ScreenDims;
Output.Position.y = 1.0f - Output.Position.y; // flip y Output.Position.y = 1.0f - Output.Position.y; // flip y
Output.Position.xy -= 0.5f; // center Output.Position.xy -= 0.5f; // center
Output.Position.xy *= 2.0f; // zoom Output.Position.xy *= 2.0f; // zoom
Output.TexCoord = PrepareVector Output.TexCoord = Input.Position.xy / ScreenDims;
? Input.Position.xy / ScreenDims
: Input.TexCoord;
Output.TexCoord += 0.5f / TargetDims; // half texel offset correction (DX9) Output.TexCoord += 0.5f / TargetDims; // half texel offset correction (DX9)
Output.SourceCoord = Input.TexCoord;
float2 ScreenCoordOffset = ShadowUVOffset;
ScreenCoordOffset = SwapXY
? ShadowUVOffset.yx
: ShadowUVOffset.xy;
Output.ScreenCoord = Input.Position.xy / ScreenDims;
Output.ScreenCoord += ScreenCoordOffset / ScreenDims;
Output.Color = Input.Color; Output.Color = Input.Color;
return Output; return Output;
@ -165,21 +164,16 @@ float4 ps_main(PS_INPUT Input) : COLOR
{ {
float2 ScreenTexelDims = 1.0f / ScreenDims; float2 ScreenTexelDims = 1.0f / ScreenDims;
float2 SourceTexelDims = 1.0f / SourceDims; float2 SourceTexelDims = 1.0f / SourceDims;
float2 SourceRes = SourceDims * SourceRect;
float2 HalfSourceRect = SourceRect * 0.5f; float2 ScreenCoord = Input.ScreenCoord;
float2 TexCoord = GetAdjustedCoords(Input.TexCoord, 0.5f);
float2 ScreenCoord = Input.ScreenCoord / ScreenDims; float2 SourceCoord = GetAdjustedCoords(Input.SourceCoord, 0.5f * SourceRect);
float2 BaseCoord = GetAdjustedCoords(Input.TexCoord, HalfSourceRect);
// Color // Color
float4 BaseColor = tex2D(DiffuseSampler, BaseCoord); float4 BaseColor = tex2D(DiffuseSampler, TexCoord);
BaseColor.a = 1.0f; BaseColor.a = 1.0f;
if (BaseCoord.x < 0.0f || BaseCoord.y < 0.0f) clip(TexCoord < 0.0f || TexCoord > 1.0f ? -1 : 1);
{
BaseColor.rgb = 0.0f;
}
// Mask Simulation (may not affect bloom) // Mask Simulation (may not affect bloom)
if (!PrepareBloom && ShadowAlpha > 0.0f) if (!PrepareBloom && ShadowAlpha > 0.0f)
@ -194,7 +188,7 @@ float4 ps_main(PS_INPUT Input) : COLOR
// ? shadowUV.yx // ? shadowUV.yx
// : shadowUV.xy; // : shadowUV.xy;
float2 screenCoord = ShadowTileMode == 0 ? ScreenCoord : BaseCoord; float2 screenCoord = ShadowTileMode == 0 ? ScreenCoord : SourceCoord;
screenCoord = SwapXY screenCoord = SwapXY
? screenCoord.yx ? screenCoord.yx
: screenCoord.xy; : screenCoord.xy;
@ -204,7 +198,7 @@ float4 ps_main(PS_INPUT Input) : COLOR
? shadowCount.yx ? shadowCount.yx
: shadowCount.xy; : shadowCount.xy;
float2 shadowTile = ((ShadowTileMode == 0 ? ScreenTexelDims : SourceTexelDims) * shadowCount); float2 shadowTile = (ShadowTileMode == 0 ? ScreenTexelDims : SourceTexelDims) * shadowCount;
shadowTile = SwapXY shadowTile = SwapXY
? shadowTile.yx ? shadowTile.yx
: shadowTile.xy; : shadowTile.xy;
@ -242,14 +236,14 @@ float4 ps_main(PS_INPUT Input) : COLOR
if (!PrepareBloom) if (!PrepareBloom)
{ {
// Scanline Simulation (may not affect vector screen) // Scanline Simulation (may not affect vector screen)
if (!PrepareVector && ScanlineAlpha > 0.0f) if (!VectorScreen && ScanlineAlpha > 0.0f)
{ {
float BrightnessOffset = (ScanlineBrightOffset * ScanlineAlpha); float BrightnessOffset = (ScanlineBrightOffset * ScanlineAlpha);
float BrightnessScale = (ScanlineBrightScale * ScanlineAlpha) + (1.0f - ScanlineAlpha); float BrightnessScale = (ScanlineBrightScale * ScanlineAlpha) + (1.0f - ScanlineAlpha);
float ColorBrightness = 0.299f * BaseColor.r + 0.587f * BaseColor.g + 0.114 * BaseColor.b; float ColorBrightness = 0.299f * BaseColor.r + 0.587f * BaseColor.g + 0.114 * BaseColor.b;
float ScanlineCoord = BaseCoord.y * SourceDims.y * ScanlineScale * PI; float ScanlineCoord = SourceCoord.y * SourceDims.y * ScanlineScale * PI;
float ScanlineCoordJitter = ScanlineOffset * PHI; float ScanlineCoordJitter = ScanlineOffset * PHI;
float ScanlineSine = sin(ScanlineCoord + ScanlineCoordJitter); float ScanlineSine = sin(ScanlineCoord + ScanlineCoordJitter);
float ScanlineWide = ScanlineHeight + max(1.0f, ScanlineHeight) * (1.0f - ColorBrightness); float ScanlineWide = ScanlineHeight + max(1.0f, ScanlineHeight) * (1.0f - ColorBrightness);
@ -260,21 +254,15 @@ float4 ps_main(PS_INPUT Input) : COLOR
} }
// Hum Bar Simulation (may not affect vector screen) // Hum Bar Simulation (may not affect vector screen)
if (!PrepareVector && HumBarAlpha > 0.0f) if (!VectorScreen && HumBarAlpha > 0.0f)
{ {
float HumBarStep = frac(TimeMilliseconds * HumBarDesync); float HumBarStep = frac(TimeMilliseconds * HumBarDesync);
float HumBarBrightness = 1.0 - frac(BaseCoord.y / SourceRect.y + HumBarStep) * HumBarAlpha; float HumBarBrightness = 1.0 - frac(SourceCoord.y / SourceRect.y + HumBarStep) * HumBarAlpha;
BaseColor.rgb *= HumBarBrightness; BaseColor.rgb *= HumBarBrightness;
} }
} }
// Output return BaseColor;
float4 Output = PrepareVector
? BaseColor * (Input.Color + float4(1.0f, 1.0f, 1.0f, 0.0f))
: BaseColor * Input.Color;
Output.a = 1.0f;
return Output;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@ -1,7 +1,11 @@
// license:BSD-3-Clause // license:BSD-3-Clause
// copyright-holders:Ryan Holtz // copyright-holders:Ryan Holtz,Themaister,ImJezze
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Prescale Effect // Pre-scale Effect
//
// Uses the hardware bilinear interpolator to avoid having to sample 4 times manually.
//
// https://github.com/libretro/common-shaders/blob/master/retro/shaders/sharp-bilinear.cg
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -13,9 +17,9 @@ texture Diffuse;
sampler DiffuseSampler = sampler_state sampler DiffuseSampler = sampler_state
{ {
Texture = <Diffuse>; Texture = <Diffuse>;
MipFilter = NONE; MipFilter = LINEAR;
MinFilter = NONE; MinFilter = LINEAR;
MagFilter = NONE; MagFilter = LINEAR;
AddressU = CLAMP; AddressU = CLAMP;
AddressV = CLAMP; AddressV = CLAMP;
AddressW = CLAMP; AddressW = CLAMP;
@ -45,11 +49,12 @@ struct PS_INPUT
}; };
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Prescale Vertex Shader // Pre-scale Vertex Shader
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
uniform float2 ScreenDims; uniform float2 ScreenDims;
uniform float2 TargetDims; uniform float2 TargetDims;
uniform float2 SourceDims;
VS_OUTPUT vs_main(VS_INPUT Input) VS_OUTPUT vs_main(VS_INPUT Input)
{ {
@ -62,22 +67,35 @@ VS_OUTPUT vs_main(VS_INPUT Input)
Output.Position.xy *= 2.0f; // zoom Output.Position.xy *= 2.0f; // zoom
Output.TexCoord = Input.TexCoord; Output.TexCoord = Input.TexCoord;
Output.TexCoord += 0.5f / TargetDims; // half texel offset correction (DX9) // Output.TexCoord += 0.5f / targetDims; // half texel offset correction (DX9)
return Output; return Output;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Prescale Pixel Shader // Pre-scale Pixel Shader
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
float4 ps_main(PS_INPUT Input) : COLOR float4 ps_main(PS_INPUT Input) : COLOR
{ {
return tex2D(DiffuseSampler, Input.TexCoord); float2 Scale = TargetDims / SourceDims;
float2 TexelDims = Input.TexCoord * SourceDims;
float2 i = floor(TexelDims);
float2 s = frac(TexelDims);
// Figure out where in the texel to sample to get the correct pre-scaled bilinear.
float2 CenterDistance = s - 0.5f;
float2 RegionRange = 0.5f - 0.5f / Scale;
float2 f = (CenterDistance - clamp(CenterDistance, -RegionRange, RegionRange)) * Scale + 0.5f;
float2 TexCoord = (i + f) / SourceDims;
return tex2D(DiffuseSampler, TexCoord);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Prescale Technique // Pre-scale Technique
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
technique DefaultTechnique technique DefaultTechnique

View File

@ -55,8 +55,7 @@ uniform float2 ScreenDims;
uniform float2 TargetDims; uniform float2 TargetDims;
uniform bool PostPass; uniform bool PostPass;
uniform bool VectorScreen;
uniform float Brighten;
VS_OUTPUT vs_main(VS_INPUT Input) VS_OUTPUT vs_main(VS_INPUT Input)
{ {
@ -70,12 +69,16 @@ VS_OUTPUT vs_main(VS_INPUT Input)
float2 targetDims = TargetDims + Epsilon; // bug: with exact target dimensions the font disappears float2 targetDims = TargetDims + Epsilon; // bug: with exact target dimensions the font disappears
Output.TexCoord = PostPass if (PostPass)
? Input.Position.xy / ScreenDims {
: Input.TexCoord; Output.TexCoord = Input.Position.xy / ScreenDims;
Output.TexCoord += PostPass Output.TexCoord += 0.5f / targetDims; // half texel offset correction (DX9)
? 0.5f / targetDims // half texel offset correction (DX9) }
: 0.0f; else
{
Output.TexCoord = Input.TexCoord;
// Output.TexCoord += 0.5f / targetDims; // half texel offset correction (DX9)
}
Output.Color = Input.Color; Output.Color = Input.Color;
@ -89,7 +92,9 @@ VS_OUTPUT vs_main(VS_INPUT Input)
float4 ps_main(PS_INPUT Input) : COLOR float4 ps_main(PS_INPUT Input) : COLOR
{ {
float4 BaseTexel = tex2D(DiffuseSampler, Input.TexCoord); float4 BaseTexel = tex2D(DiffuseSampler, Input.TexCoord);
BaseTexel *= Input.Color + float4(Brighten, Brighten, Brighten, 0.0f); BaseTexel *= PostPass && VectorScreen
? Input.Color + float4(1.0f, 1.0f, 1.0f, 0.0f)
: Input.Color;
return BaseTexel; return BaseTexel;
} }

View File

@ -78,6 +78,8 @@ public:
DWORD get_max_texture_width() { return m_texture_max_width; } DWORD get_max_texture_width() { return m_texture_max_width; }
DWORD get_max_texture_height() { return m_texture_max_height; } DWORD get_max_texture_height() { return m_texture_max_height; }
void compute_texture_size(int texwidth, int texheight, int* p_width, int* p_height);
texture_info * get_default_texture() { return m_default_texture; } texture_info * get_default_texture() { return m_default_texture; }
texture_info * get_vector_texture() { return m_vector_texture; } texture_info * get_vector_texture() { return m_vector_texture; }
@ -149,7 +151,6 @@ public:
private: private:
void prescale(); void prescale();
void compute_size(int texwidth, int texheight); void compute_size(int texwidth, int texheight);
void compute_size_subroutine(int texwidth, int texheight, int* p_width, int* p_height);
texture_manager * m_texture_manager; // texture manager pointer texture_manager * m_texture_manager; // texture manager pointer

View File

@ -72,7 +72,7 @@ static direct3dx9_loadeffect_ptr g_load_effect = NULL;
//============================================================ //============================================================
shaders::shaders() : shaders::shaders() :
d3dintf(NULL), machine(NULL), d3d(NULL), num_screens(0), curr_screen(0), curr_frame(0), write_ini(false), read_ini(false), hlsl_prescale_x(0), hlsl_prescale_y(0), bloom_count(0), d3dintf(NULL), machine(NULL), d3d(NULL), num_screens(0), curr_screen(0), curr_frame(0), bloom_count(0),
vecbuf_type(), vecbuf_index(0), vecbuf_count(0), avi_output_file(NULL), avi_frame(0), avi_copy_surface(NULL), avi_copy_texture(NULL), avi_final_target(NULL), avi_final_texture(NULL), vecbuf_type(), vecbuf_index(0), vecbuf_count(0), avi_output_file(NULL), avi_frame(0), avi_copy_surface(NULL), avi_copy_texture(NULL), avi_final_target(NULL), avi_final_texture(NULL),
black_surface(NULL), black_texture(NULL), render_snap(false), snap_rendered(false), snap_copy_target(NULL), snap_copy_texture(NULL), snap_target(NULL), snap_texture(NULL), black_surface(NULL), black_texture(NULL), render_snap(false), snap_rendered(false), snap_copy_target(NULL), snap_copy_texture(NULL), snap_target(NULL), snap_texture(NULL),
snap_width(0), snap_height(0), lines_pending(false), backbuffer(NULL), curr_effect(NULL), default_effect(NULL), prescale_effect(NULL), post_effect(NULL), distortion_effect(NULL), snap_width(0), snap_height(0), lines_pending(false), backbuffer(NULL), curr_effect(NULL), default_effect(NULL), prescale_effect(NULL), post_effect(NULL), distortion_effect(NULL),
@ -81,9 +81,6 @@ shaders::shaders() :
{ {
master_enable = false; master_enable = false;
vector_enable = true; vector_enable = true;
hlsl_prescale_x = 1;
hlsl_prescale_x = 1;
preset = -1;
shadow_texture = NULL; shadow_texture = NULL;
options = NULL; options = NULL;
paused = true; paused = true;
@ -675,8 +672,6 @@ void shaders::init(base *d3dintf, running_machine *machine, d3d::renderer *rende
windows_options &winoptions = downcast<windows_options &>(machine->options()); windows_options &winoptions = downcast<windows_options &>(machine->options());
master_enable = winoptions.d3d_hlsl_enable(); master_enable = winoptions.d3d_hlsl_enable();
hlsl_prescale_x = winoptions.d3d_hlsl_prescale_x();
hlsl_prescale_y = winoptions.d3d_hlsl_prescale_y();
snap_width = winoptions.d3d_snap_width(); snap_width = winoptions.d3d_snap_width();
snap_height = winoptions.d3d_snap_height(); snap_height = winoptions.d3d_snap_height();
@ -964,6 +959,7 @@ int shaders::create_resources(bool reset)
effects[i]->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS); effects[i]->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS);
effects[i]->add_uniform("QuadDims", uniform::UT_VEC2, uniform::CU_QUAD_DIMS); effects[i]->add_uniform("QuadDims", uniform::UT_VEC2, uniform::CU_QUAD_DIMS);
effects[i]->add_uniform("SwapXY", uniform::UT_BOOL, uniform::CU_SWAP_XY); effects[i]->add_uniform("SwapXY", uniform::UT_BOOL, uniform::CU_SWAP_XY);
effects[i]->add_uniform("VectorScreen", uniform::UT_BOOL, uniform::CU_VECTOR_SCREEN);
} }
ntsc_effect->add_uniform("CCValue", uniform::UT_FLOAT, uniform::CU_NTSC_CCFREQ); ntsc_effect->add_uniform("CCValue", uniform::UT_FLOAT, uniform::CU_NTSC_CCFREQ);
@ -1243,9 +1239,9 @@ int shaders::ntsc_pass(render_target *rt, int source_index, poly_info *poly, int
curr_effect->set_float("SignalOffset", signal_offset); curr_effect->set_float("SignalOffset", signal_offset);
next_index = rt->next_index(next_index); next_index = rt->next_index(next_index);
blit(rt->native_target[next_index], true, D3DPT_TRIANGLELIST, 0, 2); blit(rt->source_surface[next_index], true, D3DPT_TRIANGLELIST, 0, 2);
color_effect->set_texture("Diffuse", rt->native_texture[next_index]); color_effect->set_texture("Diffuse", rt->source_texture[next_index]);
return next_index; return next_index;
} }
@ -1300,7 +1296,7 @@ int shaders::color_convolution_pass(render_target *rt, int source_index, poly_in
// initial "Diffuse" texture is set in shaders::set_texture() or the result of shaders::ntsc_pass() // initial "Diffuse" texture is set in shaders::set_texture() or the result of shaders::ntsc_pass()
next_index = rt->next_index(next_index); next_index = rt->next_index(next_index);
blit(rt->native_target[next_index], true, D3DPT_TRIANGLELIST, 0, 2); blit(rt->source_surface[next_index], true, D3DPT_TRIANGLELIST, 0, 2);
return next_index; return next_index;
} }
@ -1311,10 +1307,11 @@ int shaders::prescale_pass(render_target *rt, int source_index, poly_info *poly,
curr_effect = prescale_effect; curr_effect = prescale_effect;
curr_effect->update_uniforms(); curr_effect->update_uniforms();
curr_effect->set_texture("Diffuse", rt->native_texture[next_index]); curr_effect->set_texture("Diffuse", rt->source_texture[next_index]);
next_index = rt->next_index(next_index); next_index = rt->next_index(next_index);
blit(rt->prescale_target[next_index], true, D3DPT_TRIANGLELIST, 0, 2); // blit(rt->target_surface[next_index], true, D3DPT_TRIANGLELIST, 0, 2);
blit(rt->target_surface[next_index], true, poly->get_type(), vertnum, poly->get_count());
return next_index; return next_index;
} }
@ -1334,10 +1331,11 @@ int shaders::deconverge_pass(render_target *rt, int source_index, poly_info *pol
curr_effect = deconverge_effect; curr_effect = deconverge_effect;
curr_effect->update_uniforms(); curr_effect->update_uniforms();
curr_effect->set_texture("Diffuse", rt->prescale_texture[next_index]); curr_effect->set_texture("Diffuse", rt->target_texture[next_index]);
next_index = rt->next_index(next_index); next_index = rt->next_index(next_index);
blit(rt->prescale_target[next_index], true, D3DPT_TRIANGLELIST, 0, 2); // blit(rt->target_surface[next_index], true, D3DPT_TRIANGLELIST, 0, 2);
blit(rt->target_surface[next_index], true, poly->get_type(), vertnum, poly->get_count());
return next_index; return next_index;
} }
@ -1354,10 +1352,11 @@ int shaders::defocus_pass(render_target *rt, int source_index, poly_info *poly,
curr_effect = focus_effect; curr_effect = focus_effect;
curr_effect->update_uniforms(); curr_effect->update_uniforms();
curr_effect->set_texture("Diffuse", rt->prescale_texture[next_index]); curr_effect->set_texture("Diffuse", rt->target_texture[next_index]);
next_index = rt->next_index(next_index); next_index = rt->next_index(next_index);
blit(rt->prescale_target[next_index], true, D3DPT_TRIANGLELIST, 0, 2); // blit(rt->target_surface[next_index], true, D3DPT_TRIANGLELIST, 0, 2);
blit(rt->target_surface[next_index], true, poly->get_type(), vertnum, poly->get_count());
return next_index; return next_index;
} }
@ -1374,21 +1373,23 @@ int shaders::phosphor_pass(render_target *rt, cache_target *ct, int source_index
curr_effect = phosphor_effect; curr_effect = phosphor_effect;
curr_effect->update_uniforms(); curr_effect->update_uniforms();
curr_effect->set_texture("Diffuse", rt->prescale_texture[next_index]); curr_effect->set_texture("Diffuse", rt->target_texture[next_index]);
curr_effect->set_texture("LastPass", ct->last_texture); curr_effect->set_texture("LastPass", ct->last_texture);
curr_effect->set_bool("Passthrough", false); curr_effect->set_bool("Passthrough", false);
next_index = rt->next_index(next_index); next_index = rt->next_index(next_index);
blit(rt->prescale_target[next_index], true, D3DPT_TRIANGLELIST, 0, 2); // blit(rt->target_surface[next_index], true, D3DPT_TRIANGLELIST, 0, 2);
blit(rt->target_surface[next_index], true, poly->get_type(), vertnum, poly->get_count());
// Pass along our phosphor'd screen // Pass along our phosphor'd screen
curr_effect->update_uniforms(); curr_effect->update_uniforms();
curr_effect->set_texture("Diffuse", rt->prescale_texture[next_index]); curr_effect->set_texture("Diffuse", rt->target_texture[next_index]);
curr_effect->set_texture("LastPass", rt->prescale_texture[next_index]); curr_effect->set_texture("LastPass", rt->target_texture[next_index]);
curr_effect->set_bool("Passthrough", true); curr_effect->set_bool("Passthrough", true);
// Avoid changing targets due to page flipping // Avoid changing targets due to page flipping
blit(ct->last_target, true, D3DPT_TRIANGLELIST, 0, 2); // blit(ct->last_target, true, D3DPT_TRIANGLELIST, 0, 2);
blit(ct->last_target, true, poly->get_type(), vertnum, poly->get_count());
return next_index; return next_index;
} }
@ -1397,9 +1398,6 @@ int shaders::post_pass(render_target *rt, int source_index, poly_info *poly, int
{ {
int next_index = source_index; int next_index = source_index;
bool prepare_vector =
machine->first_screen()->screen_type() == SCREEN_TYPE_VECTOR;
screen_device_iterator screen_iterator(machine->root_device()); screen_device_iterator screen_iterator(machine->root_device());
screen_device *screen = screen_iterator.first(); screen_device *screen = screen_iterator.first();
for (int i = 0; i < curr_screen; i++) for (int i = 0; i < curr_screen; i++)
@ -1429,7 +1427,7 @@ int shaders::post_pass(render_target *rt, int source_index, poly_info *poly, int
curr_effect->update_uniforms(); curr_effect->update_uniforms();
curr_effect->set_texture("ShadowTexture", shadow_texture == NULL ? NULL : shadow_texture->get_finaltex()); curr_effect->set_texture("ShadowTexture", shadow_texture == NULL ? NULL : shadow_texture->get_finaltex());
curr_effect->set_int("ShadowTileMode", options->shadow_mask_tile_mode); curr_effect->set_int("ShadowTileMode", options->shadow_mask_tile_mode);
curr_effect->set_texture("DiffuseTexture", rt->prescale_texture[next_index]); curr_effect->set_texture("DiffuseTexture", rt->target_texture[next_index]);
curr_effect->set_vector("BackColor", 3, back_color); curr_effect->set_vector("BackColor", 3, back_color);
curr_effect->set_vector("ScreenScale", 2, screen_scale); curr_effect->set_vector("ScreenScale", 2, screen_scale);
curr_effect->set_vector("ScreenOffset", 2, screen_offset); curr_effect->set_vector("ScreenOffset", 2, screen_offset);
@ -1437,10 +1435,10 @@ int shaders::post_pass(render_target *rt, int source_index, poly_info *poly, int
curr_effect->set_float("TimeMilliseconds", (float)machine->time().as_double() * 1000.0f); curr_effect->set_float("TimeMilliseconds", (float)machine->time().as_double() * 1000.0f);
curr_effect->set_float("HumBarAlpha", options->hum_bar_alpha); curr_effect->set_float("HumBarAlpha", options->hum_bar_alpha);
curr_effect->set_bool("PrepareBloom", prepare_bloom); curr_effect->set_bool("PrepareBloom", prepare_bloom);
curr_effect->set_bool("PrepareVector", prepare_vector);
next_index = rt->next_index(next_index); next_index = rt->next_index(next_index);
blit(prepare_bloom ? rt->native_target[next_index] : rt->prescale_target[next_index], true, poly->get_type(), vertnum, poly->get_count()); // blit(prepare_bloom ? rt->source_surface[next_index] : rt->target_surface[next_index], true, D3DPT_TRIANGLELIST, 0, 2);
blit(prepare_bloom ? rt->source_surface[next_index] : rt->target_surface[next_index], true, poly->get_type(), vertnum, poly->get_count());
return next_index; return next_index;
} }
@ -1455,12 +1453,8 @@ int shaders::downsample_pass(render_target *rt, int source_index, poly_info *pol
return next_index; return next_index;
} }
bool prepare_vector =
machine->first_screen()->screen_type() == SCREEN_TYPE_VECTOR;
curr_effect = downsample_effect; curr_effect = downsample_effect;
curr_effect->update_uniforms(); curr_effect->update_uniforms();
curr_effect->set_bool("PrepareVector", prepare_vector);
int bloom_index = 0; int bloom_index = 0;
float bloom_size = (d3d->get_width() < d3d->get_height()) ? d3d->get_width() : d3d->get_height(); float bloom_size = (d3d->get_width() < d3d->get_height()) ? d3d->get_width() : d3d->get_height();
@ -1474,9 +1468,10 @@ int shaders::downsample_pass(render_target *rt, int source_index, poly_info *pol
curr_effect->set_vector("TargetDims", 2, bloom_dims[bloom_index]); curr_effect->set_vector("TargetDims", 2, bloom_dims[bloom_index]);
curr_effect->set_texture("DiffuseTexture", curr_effect->set_texture("DiffuseTexture",
bloom_index == 0 bloom_index == 0
? rt->native_texture[next_index] ? rt->source_texture[next_index]
: rt->bloom_texture[bloom_index - 1]); : rt->bloom_texture[bloom_index - 1]);
// blit(rt->bloom_target[bloom_index], true, D3DPT_TRIANGLELIST, 0, 2);
blit(rt->bloom_target[bloom_index], true, poly->get_type(), vertnum, poly->get_count()); blit(rt->bloom_target[bloom_index], true, poly->get_type(), vertnum, poly->get_count());
bloom_width *= 0.5f; bloom_width *= 0.5f;
@ -1542,7 +1537,7 @@ int shaders::bloom_pass(render_target *rt, int source_index, poly_info *poly, in
curr_effect->set_float("BloomScale", options->bloom_scale); curr_effect->set_float("BloomScale", options->bloom_scale);
curr_effect->set_vector("BloomOverdrive", 3, options->bloom_overdrive); curr_effect->set_vector("BloomOverdrive", 3, options->bloom_overdrive);
curr_effect->set_texture("DiffuseA", rt->prescale_texture[next_index]); curr_effect->set_texture("DiffuseA", rt->target_texture[next_index]);
char name[9] = "Diffuse*"; char name[9] = "Diffuse*";
for (int index = 1; index < bloom_count; index++) for (int index = 1; index < bloom_count; index++)
@ -1557,7 +1552,8 @@ int shaders::bloom_pass(render_target *rt, int source_index, poly_info *poly, in
} }
next_index = rt->next_index(next_index); next_index = rt->next_index(next_index);
blit(rt->prescale_target[next_index], true, poly->get_type(), vertnum, poly->get_count()); // blit(rt->target_surface[next_index], true, D3DPT_TRIANGLELIST, 0, 2);
blit(rt->target_surface[next_index], true, poly->get_type(), vertnum, poly->get_count());
return next_index; return next_index;
} }
@ -1578,7 +1574,7 @@ int shaders::distortion_pass(render_target *rt, int source_index, poly_info *pol
int screen_count = d3d->window().target()->current_view()->screens().count(); int screen_count = d3d->window().target()->current_view()->screens().count();
// only one screen is supported // todo: only one screen is supported
if (screen_count > 1) if (screen_count > 1)
{ {
return next_index; return next_index;
@ -1586,22 +1582,26 @@ int shaders::distortion_pass(render_target *rt, int source_index, poly_info *pol
render_bounds bounds = d3d->window().target()->current_view()->bounds(); render_bounds bounds = d3d->window().target()->current_view()->bounds();
render_bounds screen_bounds = d3d->window().target()->current_view()->screen_bounds(); render_bounds screen_bounds = d3d->window().target()->current_view()->screen_bounds();
bool screen_bounds_zoomed = d3d->window().target()->zoom_to_screen();
// artworks are not supported bool screen_bounds_differ =
if (bounds.x0 != screen_bounds.x0 || bounds.x0 != screen_bounds.x0 ||
bounds.y0 != screen_bounds.y0 || bounds.y0 != screen_bounds.y0 ||
bounds.x1 != screen_bounds.x1 || bounds.x1 != screen_bounds.x1 ||
bounds.y1 != screen_bounds.y1) bounds.y1 != screen_bounds.y1;
// todo: full artworks are not supported
if (screen_bounds_differ && !screen_bounds_zoomed)
{ {
return next_index; return next_index;
} }
curr_effect = distortion_effect; curr_effect = distortion_effect;
curr_effect->update_uniforms(); curr_effect->update_uniforms();
curr_effect->set_texture("DiffuseTexture", rt->prescale_texture[next_index]); curr_effect->set_texture("DiffuseTexture", rt->target_texture[next_index]);
next_index = rt->next_index(next_index); next_index = rt->next_index(next_index);
blit(rt->prescale_target[next_index], true, poly->get_type(), vertnum, poly->get_count()); // blit(rt->target_surface[next_index], true, D3DPT_TRIANGLELIST, 0, 2);
blit(rt->target_surface[next_index], true, poly->get_type(), vertnum, poly->get_count());
return next_index; return next_index;
} }
@ -1618,7 +1618,8 @@ int shaders::vector_pass(render_target *rt, int source_index, poly_info *poly, i
curr_effect->set_vector("TimeParams", 2, time_params); curr_effect->set_vector("TimeParams", 2, time_params);
curr_effect->set_vector("LengthParams", 3, length_params); curr_effect->set_vector("LengthParams", 3, length_params);
blit(rt->prescale_target[next_index], true, poly->get_type(), vertnum, poly->get_count()); // blit(rt->target_surface[next_index], true, D3DPT_TRIANGLELIST, 0, 2);
blit(rt->target_surface[next_index], true, poly->get_type(), vertnum, poly->get_count());
return next_index; return next_index;
} }
@ -1630,12 +1631,12 @@ int shaders::vector_buffer_pass(render_target *rt, int source_index, poly_info *
curr_effect = default_effect; curr_effect = default_effect;
curr_effect->update_uniforms(); curr_effect->update_uniforms();
curr_effect->set_texture("Diffuse", rt->prescale_texture[next_index]); curr_effect->set_texture("Diffuse", rt->target_texture[next_index]);
curr_effect->set_bool("PostPass", true); curr_effect->set_bool("PostPass", true);
curr_effect->set_float("Brighten", 1.0f);
next_index = rt->next_index(next_index); next_index = rt->next_index(next_index);
blit(rt->prescale_target[next_index], true, poly->get_type(), vertnum, poly->get_count()); // blit(rt->target_surface[next_index], true, D3DPT_TRIANGLELIST, 0, 2);
blit(rt->target_surface[next_index], true, poly->get_type(), vertnum, poly->get_count());
return next_index; return next_index;
} }
@ -1644,15 +1645,11 @@ int shaders::screen_pass(render_target *rt, int source_index, poly_info *poly, i
{ {
int next_index = source_index; int next_index = source_index;
bool prepare_vector =
machine->first_screen()->screen_type() == SCREEN_TYPE_VECTOR;
curr_effect = default_effect; curr_effect = default_effect;
curr_effect->update_uniforms(); curr_effect->update_uniforms();
curr_effect->set_texture("Diffuse", rt->prescale_texture[next_index]); curr_effect->set_texture("Diffuse", rt->target_texture[next_index]);
curr_effect->set_bool("PostPass", true); curr_effect->set_bool("PostPass", true);
curr_effect->set_float("Brighten", prepare_vector ? 1.0f : 0.0f);
// we do not clear the backbuffe here because multiple screens might rendered into // we do not clear the backbuffe here because multiple screens might rendered into
blit(backbuffer, false, poly->get_type(), vertnum, poly->get_count()); blit(backbuffer, false, poly->get_type(), vertnum, poly->get_count());
@ -1677,7 +1674,6 @@ void shaders::menu_pass(poly_info *poly, int vertnum)
curr_effect = default_effect; curr_effect = default_effect;
curr_effect->update_uniforms(); curr_effect->update_uniforms();
curr_effect->set_bool("PostPass", false); curr_effect->set_bool("PostPass", false);
curr_effect->set_float("Brighten", 0.0f);
blit(NULL, false, poly->get_type(), vertnum, poly->get_count()); blit(NULL, false, poly->get_type(), vertnum, poly->get_count());
} }
@ -1706,6 +1702,7 @@ void shaders::render_quad(poly_info *poly, int vertnum)
render_target *rt = curr_render_target; render_target *rt = curr_render_target;
if (rt == NULL) if (rt == NULL)
{ {
osd_printf_verbose("Direct3D: No raster render target\n");
return; return;
} }
@ -1752,6 +1749,7 @@ void shaders::render_quad(poly_info *poly, int vertnum)
render_target *rt = curr_render_target; render_target *rt = curr_render_target;
if (rt == NULL) if (rt == NULL)
{ {
osd_printf_verbose("Direct3D: No vector render target\n");
return; return;
} }
@ -1774,6 +1772,7 @@ void shaders::render_quad(poly_info *poly, int vertnum)
render_target *rt = curr_render_target; render_target *rt = curr_render_target;
if (rt == NULL) if (rt == NULL)
{ {
osd_printf_verbose("Direct3D: No vector buffer render target\n");
return; return;
} }
@ -1836,24 +1835,14 @@ void shaders::end_draw()
} }
//============================================================
// shaders::register_prescaled_texture
//============================================================
bool shaders::register_prescaled_texture(texture_info *texture)
{
return register_texture(texture);
}
//============================================================ //============================================================
// shaders::add_cache_target - register a cache target // shaders::add_cache_target - register a cache target
//============================================================ //============================================================
bool shaders::add_cache_target(renderer* d3d, texture_info* info, int width, int height, int xprescale, int yprescale, int screen_index) bool shaders::add_cache_target(renderer* d3d, texture_info* info, int width, int height, int screen_index)
{ {
cache_target* target = (cache_target*)global_alloc_clear<cache_target>(); cache_target* target = (cache_target*)global_alloc_clear<cache_target>();
if (!target->init(d3d, d3dintf, width, height, xprescale, yprescale)) if (!target->init(d3d, d3dintf, width, height))
{ {
global_free(target); global_free(target);
return false; return false;
@ -1896,7 +1885,10 @@ render_target* shaders::get_vector_target()
void shaders::create_vector_target(render_primitive *prim) void shaders::create_vector_target(render_primitive *prim)
{ {
if (!add_render_target(d3d, NULL, d3d->get_width(), d3d->get_height(), 1, 1)) int width = d3d->get_width();
int height = d3d->get_height();
if (!add_render_target(d3d, NULL, width, height, width, height))
{ {
vector_enable = false; vector_enable = false;
} }
@ -1907,7 +1899,7 @@ void shaders::create_vector_target(render_primitive *prim)
// shaders::add_render_target - register a render target // shaders::add_render_target - register a render target
//============================================================ //============================================================
bool shaders::add_render_target(renderer* d3d, texture_info* info, int width, int height, int xprescale, int yprescale) bool shaders::add_render_target(renderer* d3d, texture_info* info, int width, int height, int target_width, int target_height)
{ {
UINT32 screen_index = 0; UINT32 screen_index = 0;
UINT32 page_index = 0; UINT32 page_index = 0;
@ -1934,7 +1926,7 @@ bool shaders::add_render_target(renderer* d3d, texture_info* info, int width, in
render_target* target = (render_target*)global_alloc_clear<render_target>(); render_target* target = (render_target*)global_alloc_clear<render_target>();
if (!target->init(d3d, d3dintf, width, height, xprescale, yprescale)) if (!target->init(d3d, d3dintf, width, height, target_width, target_height))
{ {
global_free(target); global_free(target);
return false; return false;
@ -1951,7 +1943,7 @@ bool shaders::add_render_target(renderer* d3d, texture_info* info, int width, in
target->height = d3d->get_height(); target->height = d3d->get_height();
} }
HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, target->prescale_target[0]); HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, target->target_surface[0]);
if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result);
result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0);
if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result);
@ -1964,7 +1956,7 @@ bool shaders::add_render_target(renderer* d3d, texture_info* info, int width, in
cache_target* cache = find_cache_target(target->screen_index, target->width, target->height); cache_target* cache = find_cache_target(target->screen_index, target->width, target->height);
if (cache == NULL) if (cache == NULL)
{ {
if (!add_cache_target(d3d, info, width, height, xprescale, yprescale, target->screen_index)) if (!add_cache_target(d3d, info, target_width, target_height, target->screen_index))
{ {
global_free(target); global_free(target);
return false; return false;
@ -2000,11 +1992,6 @@ void shaders::enumerate_screens()
bool shaders::register_texture(texture_info *texture) bool shaders::register_texture(texture_info *texture)
{ {
int width = texture->get_width();
int height = texture->get_height();
int xscale = texture->get_xscale();
int yscale = texture->get_yscale();
if (!master_enable || !d3dintf->post_fx_available) if (!master_enable || !d3dintf->post_fx_available)
{ {
return false; return false;
@ -2012,31 +1999,7 @@ bool shaders::register_texture(texture_info *texture)
enumerate_screens(); enumerate_screens();
// Find the nearest prescale factor that is over our screen size if (!add_render_target(d3d, texture, texture->get_width(), texture->get_height(), d3d->get_width(), d3d->get_height()))
if (hlsl_prescale_x < 1)
{
hlsl_prescale_x = 1;
while (width * xscale * hlsl_prescale_x <= d3d->get_width())
{
hlsl_prescale_x++;
}
hlsl_prescale_x--;
}
if (hlsl_prescale_y < 1)
{
hlsl_prescale_y = 1;
while (height * yscale * hlsl_prescale_y <= d3d->get_height())
{
hlsl_prescale_y++;
}
hlsl_prescale_y--;
}
hlsl_prescale_x = hlsl_prescale_x < 1 ? 1 : hlsl_prescale_x;
hlsl_prescale_y = hlsl_prescale_y < 1 ? 1 : hlsl_prescale_y;
if (!add_render_target(d3d, texture, width, height, xscale * hlsl_prescale_x, yscale * hlsl_prescale_y))
{ {
return false; return false;
} }
@ -3062,28 +3025,25 @@ void uniform::update()
vec2f sourcedims = shadersys->curr_texture->get_rawdims(); vec2f sourcedims = shadersys->curr_texture->get_rawdims();
m_shader->set_vector("SourceDims", 2, &sourcedims.c.x); m_shader->set_vector("SourceDims", 2, &sourcedims.c.x);
} }
else
{
vec2f sourcedims = d3d->get_dims();
m_shader->set_vector("SourceDims", 2, &sourcedims.c.x);
}
break; break;
} }
case CU_SOURCE_RECT: case CU_SOURCE_RECT:
{ {
bool prepare_vector =
d3d->window().machine().first_screen()->screen_type() == SCREEN_TYPE_VECTOR;
if (prepare_vector)
{
float delta[2] = { 1.0f, 1.0f };
m_shader->set_vector("SourceRect", 2, delta);
break;
}
if (shadersys->curr_texture != NULL) if (shadersys->curr_texture != NULL)
{ {
vec2f delta = shadersys->curr_texture->get_uvstop() - shadersys->curr_texture->get_uvstart(); vec2f delta = shadersys->curr_texture->get_uvstop() - shadersys->curr_texture->get_uvstart();
m_shader->set_vector("SourceRect", 2, &delta.c.x); m_shader->set_vector("SourceRect", 2, &delta.c.x);
break;
} }
else
{
float delta[2] = { 1.0f, 1.0f };
m_shader->set_vector("SourceRect", 2, delta);
}
break; break;
} }
case CU_TARGET_DIMS: case CU_TARGET_DIMS:
@ -3117,12 +3077,14 @@ void uniform::update()
(d3d->window().target()->orientation() & ROT90) == ROT90 || (d3d->window().target()->orientation() & ROT90) == ROT90 ||
(d3d->window().target()->orientation() & ROT270) == ROT270; (d3d->window().target()->orientation() & ROT270) == ROT270;
m_shader->set_bool("SwapXY", orientation_swap_xy ^ rotation_swap_xy); m_shader->set_bool("SwapXY", orientation_swap_xy ^ rotation_swap_xy);
break;
} }
case CU_ORIENTATION_SWAP: case CU_ORIENTATION_SWAP:
{ {
bool orientation_swap_xy = bool orientation_swap_xy =
(d3d->window().machine().system().flags & ORIENTATION_SWAP_XY) == ORIENTATION_SWAP_XY; (d3d->window().machine().system().flags & ORIENTATION_SWAP_XY) == ORIENTATION_SWAP_XY;
m_shader->set_bool("OrientationSwapXY", orientation_swap_xy); m_shader->set_bool("OrientationSwapXY", orientation_swap_xy);
break;
} }
case CU_ROTATION_SWAP: case CU_ROTATION_SWAP:
@ -3131,6 +3093,7 @@ void uniform::update()
(d3d->window().target()->orientation() & ROT90) == ROT90 || (d3d->window().target()->orientation() & ROT90) == ROT90 ||
(d3d->window().target()->orientation() & ROT270) == ROT270; (d3d->window().target()->orientation() & ROT270) == ROT270;
m_shader->set_bool("RotationSwapXY", rotation_swap_xy); m_shader->set_bool("RotationSwapXY", rotation_swap_xy);
break;
} }
case CU_ROTATION_TYPE: case CU_ROTATION_TYPE:
{ {
@ -3143,6 +3106,14 @@ void uniform::update()
? 3 ? 3
: 0; : 0;
m_shader->set_int("RotationType", rotation_type); m_shader->set_int("RotationType", rotation_type);
break;
}
case CU_VECTOR_SCREEN:
{
bool vector_screen =
d3d->window().machine().first_screen()->screen_type() == SCREEN_TYPE_VECTOR;
m_shader->set_bool("VectorScreen", vector_screen);
break;
} }
case CU_NTSC_CCFREQ: case CU_NTSC_CCFREQ:

View File

@ -54,6 +54,7 @@ public:
CU_ORIENTATION_SWAP, CU_ORIENTATION_SWAP,
CU_ROTATION_SWAP, CU_ROTATION_SWAP,
CU_ROTATION_TYPE, CU_ROTATION_TYPE,
CU_VECTOR_SCREEN,
CU_NTSC_CCFREQ, CU_NTSC_CCFREQ,
CU_NTSC_A, CU_NTSC_A,
@ -292,9 +293,8 @@ public:
void render_quad(poly_info *poly, int vertnum); void render_quad(poly_info *poly, int vertnum);
bool register_texture(texture_info *texture); bool register_texture(texture_info *texture);
bool register_prescaled_texture(texture_info *texture); bool add_render_target(renderer* d3d, texture_info* info, int width, int height, int target_width, int target_height);
bool add_render_target(renderer* d3d, texture_info* info, int width, int height, int xprescale, int yprescale); bool add_cache_target(renderer* d3d, texture_info* info, int width, int height, int screen_index);
bool add_cache_target(renderer* d3d, texture_info* info, int width, int height, int xprescale, int yprescale, int screen_index);
void window_save(); void window_save();
void window_record(); void window_record();
@ -379,13 +379,8 @@ private:
int curr_screen; // current screen for render target operations int curr_screen; // current screen for render target operations
int curr_frame; // current frame (0/1) of a screen for render target operations int curr_frame; // current frame (0/1) of a screen for render target operations
int lastidx; // index of the last-encountered target int lastidx; // index of the last-encountered target
bool write_ini; // enable external ini saving
bool read_ini; // enable external ini loading
int hlsl_prescale_x; // hlsl prescale x
int hlsl_prescale_y; // hlsl prescale y
float bloom_dims[11][2]; // bloom texture dimensions float bloom_dims[11][2]; // bloom texture dimensions
int bloom_count; // count of used bloom textures int bloom_count; // count of used bloom textures
int preset; // preset, if relevant
bitmap_argb32 shadow_bitmap; // shadow mask bitmap for post-processing shader bitmap_argb32 shadow_bitmap; // shadow mask bitmap for post-processing shader
texture_info * shadow_texture; // shadow mask texture for post-processing shader texture_info * shadow_texture; // shadow mask texture for post-processing shader
hlsl_options * options; // current options hlsl_options * options; // current options

View File

@ -247,6 +247,7 @@ render_primitive_list *d3d::renderer::get_primitives()
} }
if (m_shaders != NULL) if (m_shaders != NULL)
{ {
// do not transform primitives (scale, offset) if shaders are enabled, the shaders will handle the transformation
window().target()->set_transform_primitives(!m_shaders->enabled()); window().target()->set_transform_primitives(!m_shaders->enabled());
} }
return &window().target()->get_primitives(); return &window().target()->get_primitives();
@ -470,6 +471,63 @@ texture_manager::~texture_manager()
{ {
} }
//============================================================
// texture_manager::compute_texture_size
//============================================================
void texture_manager::compute_texture_size(int texwidth, int texheight, int* p_width, int* p_height)
{
int finalheight = texheight;
int finalwidth = texwidth;
// round width/height up to nearest power of 2 if we need to
if (!(get_texture_caps() & D3DPTEXTURECAPS_NONPOW2CONDITIONAL))
{
// first the width
if (finalwidth & (finalwidth - 1))
{
finalwidth |= finalwidth >> 1;
finalwidth |= finalwidth >> 2;
finalwidth |= finalwidth >> 4;
finalwidth |= finalwidth >> 8;
finalwidth++;
}
// then the height
if (finalheight & (finalheight - 1))
{
finalheight |= finalheight >> 1;
finalheight |= finalheight >> 2;
finalheight |= finalheight >> 4;
finalheight |= finalheight >> 8;
finalheight++;
}
}
// round up to square if we need to
if (get_texture_caps() & D3DPTEXTURECAPS_SQUAREONLY)
{
if (finalwidth < finalheight)
finalwidth = finalheight;
else
finalheight = finalwidth;
}
// adjust the aspect ratio if we need to
while (finalwidth < finalheight && finalheight / finalwidth > get_max_texture_aspect())
{
finalwidth *= 2;
}
while (finalheight < finalwidth && finalwidth / finalheight > get_max_texture_aspect())
{
finalheight *= 2;
}
*p_width = finalwidth;
*p_height = finalheight;
}
void texture_manager::create_resources() void texture_manager::create_resources()
{ {
// experimental: load a PNG to use for vector rendering; it is treated // experimental: load a PNG to use for vector rendering; it is treated
@ -1925,18 +1983,20 @@ texture_info::texture_info(texture_manager *manager, const render_texinfo* texso
m_d3dsurface = NULL; m_d3dsurface = NULL;
m_d3dfinaltex = NULL; m_d3dfinaltex = NULL;
// compute the size
compute_size(texsource->width, texsource->height);
// non-screen textures are easy // non-screen textures are easy
if (!PRIMFLAG_GET_SCREENTEX(flags)) if (!PRIMFLAG_GET_SCREENTEX(flags))
{ {
// required to compute the size
m_type = TEXTURE_TYPE_PLAIN;
// compute the size
compute_size(texsource->width, texsource->height);
assert(PRIMFLAG_TEXFORMAT(flags) != TEXFORMAT_YUY16); assert(PRIMFLAG_TEXFORMAT(flags) != TEXFORMAT_YUY16);
result = (*d3dintf->device.create_texture)(m_renderer->get_device(), m_rawdims.c.x, m_rawdims.c.y, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_d3dtex); result = (*d3dintf->device.create_texture)(m_renderer->get_device(), m_rawdims.c.x, m_rawdims.c.y, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_d3dtex);
if (result != D3D_OK) if (result != D3D_OK)
goto error; goto error;
m_d3dfinaltex = m_d3dtex; m_d3dfinaltex = m_d3dtex;
m_type = TEXTURE_TYPE_PLAIN;
} }
// screen textures are allocated differently // screen textures are allocated differently
@ -1994,14 +2054,19 @@ texture_info::texture_info(texture_manager *manager, const render_texinfo* texso
m_xprescale = m_yprescale = 1; m_xprescale = m_yprescale = 1;
} }
// screen textures with no prescaling are pretty easy // screen textures with no prescaling are pretty easy and shaders handle prescale itself
if (m_xprescale == 1 && m_yprescale == 1) if ((m_xprescale == 1 && m_yprescale == 1) || m_renderer->get_shaders()->enabled())
{ {
// required to compute the size
m_type = m_texture_manager->is_dynamic_supported() ? TEXTURE_TYPE_DYNAMIC : TEXTURE_TYPE_PLAIN;
// compute the size
compute_size(texsource->width, texsource->height);
result = (*d3dintf->device.create_texture)(m_renderer->get_device(), m_rawdims.c.x, m_rawdims.c.y, 1, usage, format, pool, &m_d3dtex); result = (*d3dintf->device.create_texture)(m_renderer->get_device(), m_rawdims.c.x, m_rawdims.c.y, 1, usage, format, pool, &m_d3dtex);
if (result == D3D_OK) if (result == D3D_OK)
{ {
m_d3dfinaltex = m_d3dtex; m_d3dfinaltex = m_d3dtex;
m_type = m_texture_manager->is_dynamic_supported() ? TEXTURE_TYPE_DYNAMIC : TEXTURE_TYPE_PLAIN;
if (m_renderer->get_shaders()->enabled() && !m_renderer->get_shaders()->register_texture(this)) if (m_renderer->get_shaders()->enabled() && !m_renderer->get_shaders()->register_texture(this))
{ {
goto error; goto error;
@ -2010,7 +2075,6 @@ texture_info::texture_info(texture_manager *manager, const render_texinfo* texso
break; break;
} }
} }
// screen textures with prescaling require two allocations // screen textures with prescaling require two allocations
else else
{ {
@ -2018,23 +2082,32 @@ texture_info::texture_info(texture_manager *manager, const render_texinfo* texso
// (won't work for YUY textures) // (won't work for YUY textures)
if (m_texture_manager->is_stretch_supported() && PRIMFLAG_GET_TEXFORMAT(flags) != TEXFORMAT_YUY16) if (m_texture_manager->is_stretch_supported() && PRIMFLAG_GET_TEXFORMAT(flags) != TEXFORMAT_YUY16)
{ {
// required to compute the size
m_type = TEXTURE_TYPE_SURFACE;
// compute the size
compute_size(texsource->width, texsource->height);
result = (*d3dintf->device.create_offscreen_plain_surface)(m_renderer->get_device(), m_rawdims.c.x, m_rawdims.c.y, format, D3DPOOL_DEFAULT, &m_d3dsurface); result = (*d3dintf->device.create_offscreen_plain_surface)(m_renderer->get_device(), m_rawdims.c.x, m_rawdims.c.y, format, D3DPOOL_DEFAULT, &m_d3dsurface);
if (result != D3D_OK) if (result != D3D_OK)
{ {
continue; continue;
} }
m_type = TEXTURE_TYPE_SURFACE;
} }
// otherwise, we allocate a dynamic texture for the source // otherwise, we allocate a dynamic texture for the source
else else
{ {
// required to compute the size
m_type = m_texture_manager->is_dynamic_supported() ? TEXTURE_TYPE_DYNAMIC : TEXTURE_TYPE_PLAIN;
// compute the size
compute_size(texsource->width, texsource->height);
result = (*d3dintf->device.create_texture)(m_renderer->get_device(), m_rawdims.c.x, m_rawdims.c.y, 1, usage, format, pool, &m_d3dtex); result = (*d3dintf->device.create_texture)(m_renderer->get_device(), m_rawdims.c.x, m_rawdims.c.y, 1, usage, format, pool, &m_d3dtex);
if (result != D3D_OK) if (result != D3D_OK)
{ {
continue; continue;
} }
m_type = m_texture_manager->is_dynamic_supported() ? TEXTURE_TYPE_DYNAMIC : TEXTURE_TYPE_PLAIN;
} }
// for the target surface, we allocate a render target texture // for the target surface, we allocate a render target texture
@ -2043,15 +2116,13 @@ texture_info::texture_info(texture_manager *manager, const render_texinfo* texso
// target surfaces typically cannot be YCbCr, so we always pick RGB in that case // target surfaces typically cannot be YCbCr, so we always pick RGB in that case
D3DFORMAT finalfmt = (format != m_texture_manager->get_yuv_format()) ? format : D3DFMT_A8R8G8B8; D3DFORMAT finalfmt = (format != m_texture_manager->get_yuv_format()) ? format : D3DFMT_A8R8G8B8;
result = (*d3dintf->device.create_texture)(m_renderer->get_device(), scwidth, scheight, 1, D3DUSAGE_RENDERTARGET, finalfmt, D3DPOOL_DEFAULT, &m_d3dfinaltex); result = (*d3dintf->device.create_texture)(m_renderer->get_device(), scwidth, scheight, 1, D3DUSAGE_RENDERTARGET, finalfmt, D3DPOOL_DEFAULT, &m_d3dfinaltex);
if (result == D3D_OK) if (result == D3D_OK)
{ {
if (m_renderer->get_shaders()->enabled() && !m_renderer->get_shaders()->register_prescaled_texture(this))
{
goto error;
}
break; break;
} }
(*d3dintf->texture.release)(m_d3dtex); (*d3dintf->texture.release)(m_d3dtex);
m_d3dtex = NULL; m_d3dtex = NULL;
} }
@ -2061,7 +2132,6 @@ texture_info::texture_info(texture_manager *manager, const render_texinfo* texso
// copy the data to the texture // copy the data to the texture
set_data(texsource, flags); set_data(texsource, flags);
//texsource->osdhandle = (void*)this;
// add us to the texture list // add us to the texture list
if(m_texture_manager->get_texlist() != NULL) if(m_texture_manager->get_texlist() != NULL)
m_texture_manager->get_texlist()->m_prev = this; m_texture_manager->get_texlist()->m_prev = this;
@ -2080,63 +2150,6 @@ error:
} }
//============================================================
// texture_info::compute_size_subroutine
//============================================================
void texture_info::compute_size_subroutine(int texwidth, int texheight, int* p_width, int* p_height)
{
int finalheight = texheight;
int finalwidth = texwidth;
// round width/height up to nearest power of 2 if we need to
if (!(m_texture_manager->get_texture_caps() & D3DPTEXTURECAPS_NONPOW2CONDITIONAL))
{
// first the width
if (finalwidth & (finalwidth - 1))
{
finalwidth |= finalwidth >> 1;
finalwidth |= finalwidth >> 2;
finalwidth |= finalwidth >> 4;
finalwidth |= finalwidth >> 8;
finalwidth++;
}
// then the height
if (finalheight & (finalheight - 1))
{
finalheight |= finalheight >> 1;
finalheight |= finalheight >> 2;
finalheight |= finalheight >> 4;
finalheight |= finalheight >> 8;
finalheight++;
}
}
// round up to square if we need to
if (m_texture_manager->get_texture_caps() & D3DPTEXTURECAPS_SQUAREONLY)
{
if (finalwidth < finalheight)
finalwidth = finalheight;
else
finalheight = finalwidth;
}
// adjust the aspect ratio if we need to
while (finalwidth < finalheight && finalheight / finalwidth > m_texture_manager->get_max_texture_aspect())
{
finalwidth *= 2;
}
while (finalheight < finalwidth && finalwidth / finalheight > m_texture_manager->get_max_texture_aspect())
{
finalheight *= 2;
}
*p_width = finalwidth;
*p_height = finalheight;
}
//============================================================ //============================================================
// texture_info::compute_size // texture_info::compute_size
//============================================================ //============================================================
@ -2149,19 +2162,30 @@ void texture_info::compute_size(int texwidth, int texheight)
m_xborderpix = 0; m_xborderpix = 0;
m_yborderpix = 0; m_yborderpix = 0;
bool shaders_enabled = m_renderer->get_shaders()->enabled();
bool wrap_texture = (m_flags & PRIMFLAG_TEXWRAP_MASK) == PRIMFLAG_TEXWRAP_MASK;
bool border_texture = ENABLE_BORDER_PIX && !wrap_texture;
bool surface_texture = m_type == TEXTURE_TYPE_SURFACE;
// skip border when shaders are enabled and we're not creating a surface (UI) texture
if (!shaders_enabled || surface_texture)
{
// if we're not wrapping, add a 1-2 pixel border on all sides // if we're not wrapping, add a 1-2 pixel border on all sides
if (ENABLE_BORDER_PIX && !(m_flags & PRIMFLAG_TEXWRAP_MASK)) if (border_texture)
{ {
// note we need 2 pixels in X for YUY textures // note we need 2 pixels in X for YUY textures
m_xborderpix = (PRIMFLAG_GET_TEXFORMAT(m_flags) == TEXFORMAT_YUY16) ? 2 : 1; m_xborderpix = (PRIMFLAG_GET_TEXFORMAT(m_flags) == TEXFORMAT_YUY16) ? 2 : 1;
m_yborderpix = 1; m_yborderpix = 1;
} }
}
// compute final texture size
finalwidth += 2 * m_xborderpix; finalwidth += 2 * m_xborderpix;
finalheight += 2 * m_yborderpix; finalheight += 2 * m_yborderpix;
compute_size_subroutine(finalwidth, finalheight, &finalwidth, &finalheight); // take texture size as given when shaders are enabled and we're not creating a surface (UI) texture, still update wrapped textures
if (!shaders_enabled || surface_texture || wrap_texture)
{
m_texture_manager->compute_texture_size(finalwidth, finalheight, &finalwidth, &finalheight);
// if we added pixels for the border, and that just barely pushed us over, take it back // if we added pixels for the border, and that just barely pushed us over, take it back
if (finalwidth > m_texture_manager->get_max_texture_width() || finalheight > m_texture_manager->get_max_texture_height()) if (finalwidth > m_texture_manager->get_max_texture_width() || finalheight > m_texture_manager->get_max_texture_height())
@ -2172,7 +2196,8 @@ void texture_info::compute_size(int texwidth, int texheight)
m_xborderpix = 0; m_xborderpix = 0;
m_yborderpix = 0; m_yborderpix = 0;
compute_size_subroutine(finalwidth, finalheight, &finalwidth, &finalheight); m_texture_manager->compute_texture_size(finalwidth, finalheight, &finalwidth, &finalheight);
}
} }
// if we're above the max width/height, do what? // if we're above the max width/height, do what?
@ -2751,18 +2776,20 @@ cache_target::~cache_target()
// cache_target::init - initializes a target cache // cache_target::init - initializes a target cache
//============================================================ //============================================================
bool cache_target::init(renderer *d3d, base *d3dintf, int width, int height, int prescale_x, int prescale_y) bool cache_target::init(renderer *d3d, base *d3dintf, int target_width, int target_height)
{ {
HRESULT result = (*d3dintf->device.create_texture)(d3d->get_device(), width * prescale_x, height * prescale_y, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &last_texture); // d3d->get_texture_manager()->compute_texture_size(target_width, target_height, &target_width, &target_height);
this->target_width = target_width;
this->target_height = target_height;
HRESULT result = (*d3dintf->device.create_texture)(d3d->get_device(), target_width, target_height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &last_texture);
if (result != D3D_OK) if (result != D3D_OK)
{ {
return false; return false;
} }
(*d3dintf->texture.get_surface_level)(last_texture, 0, &last_target); (*d3dintf->texture.get_surface_level)(last_texture, 0, &last_target);
target_width = width * prescale_x;
target_height = height * prescale_y;
return true; return true;
} }
@ -2789,25 +2816,25 @@ render_target::~render_target()
for (int index = 0; index < 2; index++) for (int index = 0; index < 2; index++)
{ {
if (native_texture[index] != NULL) if (source_texture[index] != NULL)
{ {
(*d3dintf->texture.release)(native_texture[index]); (*d3dintf->texture.release)(source_texture[index]);
native_texture[index] = NULL; source_texture[index] = NULL;
} }
if (native_target[index] != NULL) if (source_surface[index] != NULL)
{ {
(*d3dintf->surface.release)(native_target[index]); (*d3dintf->surface.release)(source_surface[index]);
native_target[index] = NULL; source_surface[index] = NULL;
} }
if (prescale_texture[index] != NULL) if (target_texture[index] != NULL)
{ {
(*d3dintf->texture.release)(prescale_texture[index]); (*d3dintf->texture.release)(target_texture[index]);
prescale_texture[index] = NULL; target_texture[index] = NULL;
} }
if (prescale_target[index] != NULL) if (target_surface[index] != NULL)
{ {
(*d3dintf->surface.release)(prescale_target[index]); (*d3dintf->surface.release)(target_surface[index]);
prescale_target[index] = NULL; target_surface[index] = NULL;
} }
} }
} }
@ -2817,31 +2844,39 @@ render_target::~render_target()
// render_target::init - initializes a render target // render_target::init - initializes a render target
//============================================================ //============================================================
bool render_target::init(renderer *d3d, base *d3dintf, int width, int height, int prescale_x, int prescale_y) bool render_target::init(renderer *d3d, base *d3dintf, int width, int height, int target_width, int target_height)
{ {
HRESULT result; HRESULT result;
// d3d->get_texture_manager()->compute_texture_size(target_width, target_height, &target_width, &target_height);
this->width = width;
this->height = height;
this->target_width = target_width;
this->target_height = target_height;
for (int index = 0; index < 2; index++) for (int index = 0; index < 2; index++)
{ {
result = (*d3dintf->device.create_texture)(d3d->get_device(), width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &native_texture[index]); result = (*d3dintf->device.create_texture)(d3d->get_device(), width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &source_texture[index]);
if (result != D3D_OK) if (result != D3D_OK)
{ {
return false; return false;
} }
(*d3dintf->texture.get_surface_level)(native_texture[index], 0, &native_target[index]); (*d3dintf->texture.get_surface_level)(source_texture[index], 0, &source_surface[index]);
result = (*d3dintf->device.create_texture)(d3d->get_device(), width * prescale_x, height * prescale_y, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &prescale_texture[index]); result = (*d3dintf->device.create_texture)(d3d->get_device(), target_width, target_height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &target_texture[index]);
if (result != D3D_OK) if (result != D3D_OK)
{ {
return false; return false;
} }
(*d3dintf->texture.get_surface_level)(prescale_texture[index], 0, &prescale_target[index]); (*d3dintf->texture.get_surface_level)(target_texture[index], 0, &target_surface[index]);
} }
int bloom_index = 0; int bloom_index = 0;
float bloom_size = (d3d->get_width() < d3d->get_height()) ? d3d->get_width() : d3d->get_height(); float bloom_width = target_width;
float bloom_width = d3d->get_width(); float bloom_height = target_height;
float bloom_height = d3d->get_height(); float bloom_size = bloom_width < bloom_height ? bloom_width : bloom_height;
for (; bloom_size >= 2.0f && bloom_index < 11; bloom_size *= 0.5f) for (; bloom_size >= 2.0f && bloom_index < 11; bloom_size *= 0.5f)
{ {
bloom_width *= 0.5f; bloom_width *= 0.5f;
@ -2857,12 +2892,6 @@ bool render_target::init(renderer *d3d, base *d3dintf, int width, int height, in
bloom_index++; bloom_index++;
} }
this->width = width;
this->height = height;
target_width = width * prescale_x;
target_height = height * prescale_y;
return true; return true;
} }

View File

@ -38,7 +38,7 @@ public:
cache_target() { } cache_target() { }
~cache_target(); ~cache_target();
bool init(renderer *d3d, base *d3dintf, int width, int height, int prescale_x, int prescale_y); bool init(renderer *d3d, base *d3dintf, int target_width, int target_height);
surface *last_target; surface *last_target;
texture *last_texture; texture *last_texture;
@ -65,16 +65,13 @@ public:
render_target() { } render_target() { }
~render_target(); ~render_target();
bool init(renderer *d3d, base *d3dintf, int width, int height, int prescale_x, int prescale_y); bool init(renderer *d3d, base *d3dintf, int width, int height, int target_width, int target_height);
int next_index(int index) { return ++index > 1 ? 0 : index; } int next_index(int index) { return ++index > 1 ? 0 : index; }
// real target dimension // real target dimension
int target_width; int target_width;
int target_height; int target_height;
int prescale_x;
int prescale_y;
// only used to identify/find the render target // only used to identify/find the render target
int width; int width;
int height; int height;
@ -82,10 +79,10 @@ public:
int screen_index; int screen_index;
int page_index; int page_index;
surface *prescale_target[2]; surface *target_surface[2];
texture *prescale_texture[2]; texture *target_texture[2];
surface *native_target[2]; surface *source_surface[2];
texture *native_texture[2]; texture *source_texture[2];
render_target *next; render_target *next;
render_target *prev; render_target *prev;

View File

@ -283,8 +283,6 @@ const options_entry windows_options::s_option_entries[] =
{ NULL, NULL, OPTION_HEADER, "DIRECT3D POST-PROCESSING OPTIONS" }, { NULL, NULL, OPTION_HEADER, "DIRECT3D POST-PROCESSING OPTIONS" },
{ WINOPTION_HLSL_ENABLE";hlsl", "0", OPTION_BOOLEAN, "enables HLSL post-processing (PS3.0 required)" }, { WINOPTION_HLSL_ENABLE";hlsl", "0", OPTION_BOOLEAN, "enables HLSL post-processing (PS3.0 required)" },
{ WINOPTION_HLSLPATH, "hlsl", OPTION_STRING, "path to hlsl files" }, { WINOPTION_HLSLPATH, "hlsl", OPTION_STRING, "path to hlsl files" },
{ WINOPTION_HLSL_PRESCALE_X, "0", OPTION_INTEGER, "HLSL pre-scale override factor for X (0 for auto)" },
{ WINOPTION_HLSL_PRESCALE_Y, "0", OPTION_INTEGER, "HLSL pre-scale override factor for Y (0 for auto)" },
{ WINOPTION_HLSL_WRITE, NULL, OPTION_STRING, "enables HLSL AVI writing (huge disk bandwidth suggested)" }, { WINOPTION_HLSL_WRITE, NULL, OPTION_STRING, "enables HLSL AVI writing (huge disk bandwidth suggested)" },
{ WINOPTION_HLSL_SNAP_WIDTH, "2048", OPTION_STRING, "HLSL upscaled-snapshot width" }, { WINOPTION_HLSL_SNAP_WIDTH, "2048", OPTION_STRING, "HLSL upscaled-snapshot width" },
{ WINOPTION_HLSL_SNAP_HEIGHT, "1536", OPTION_STRING, "HLSL upscaled-snapshot height" }, { WINOPTION_HLSL_SNAP_HEIGHT, "1536", OPTION_STRING, "HLSL upscaled-snapshot height" },

View File

@ -31,8 +31,6 @@
// core post-processing options // core post-processing options
#define WINOPTION_HLSL_ENABLE "hlsl_enable" #define WINOPTION_HLSL_ENABLE "hlsl_enable"
#define WINOPTION_HLSLPATH "hlslpath" #define WINOPTION_HLSLPATH "hlslpath"
#define WINOPTION_HLSL_PRESCALE_X "hlsl_prescale_x"
#define WINOPTION_HLSL_PRESCALE_Y "hlsl_prescale_y"
#define WINOPTION_HLSL_WRITE "hlsl_write" #define WINOPTION_HLSL_WRITE "hlsl_write"
#define WINOPTION_HLSL_SNAP_WIDTH "hlsl_snap_width" #define WINOPTION_HLSL_SNAP_WIDTH "hlsl_snap_width"
#define WINOPTION_HLSL_SNAP_HEIGHT "hlsl_snap_height" #define WINOPTION_HLSL_SNAP_HEIGHT "hlsl_snap_height"
@ -138,8 +136,6 @@ public:
const char *screen_post_fx_dir() const { return value(WINOPTION_HLSLPATH); } const char *screen_post_fx_dir() const { return value(WINOPTION_HLSLPATH); }
bool d3d_hlsl_enable() const { return bool_value(WINOPTION_HLSL_ENABLE); } bool d3d_hlsl_enable() const { return bool_value(WINOPTION_HLSL_ENABLE); }
const char *d3d_hlsl_write() const { return value(WINOPTION_HLSL_WRITE); } const char *d3d_hlsl_write() const { return value(WINOPTION_HLSL_WRITE); }
int d3d_hlsl_prescale_x() const { return int_value(WINOPTION_HLSL_PRESCALE_X); }
int d3d_hlsl_prescale_y() const { return int_value(WINOPTION_HLSL_PRESCALE_Y); }
int d3d_snap_width() const { return int_value(WINOPTION_HLSL_SNAP_WIDTH); } int d3d_snap_width() const { return int_value(WINOPTION_HLSL_SNAP_WIDTH); }
int d3d_snap_height() const { return int_value(WINOPTION_HLSL_SNAP_HEIGHT); } int d3d_snap_height() const { return int_value(WINOPTION_HLSL_SNAP_HEIGHT); }
int screen_shadow_mask_tile_mode() const { return int_value(WINOPTION_SHADOW_MASK_TILE_MODE); } int screen_shadow_mask_tile_mode() const { return int_value(WINOPTION_SHADOW_MASK_TILE_MODE); }