mirror of
https://github.com/holub/mame
synced 2025-10-04 16:34:53 +03:00
Refactoring, Fixes and Cleanup
- added distortion pass, which is applied after the bloom pass - moved vignetting, curvature, round corners and reflection effect to distortion pass - disabled distortion pass for multi screens and activated artworks due to not yet fixed misalignments - disabled scanlines for vector rendering in post pass shader - removed prescale knowledge from downsample, bloom and post pass shader - fixed half pixel offset in most shaders - fixed position of reflection effect when screen is rotated or flipped - fixed roundness of round corners in any aspect ratio - fixed shadow mask bleeding (nearly completly) - added bounds() and screen_bounds() getter to layout_view - added current_view() getter to render_target - some cleanup and refactoring
This commit is contained in:
parent
37f6ff0b65
commit
062e6e0383
@ -171,13 +171,33 @@ struct PS_INPUT
|
||||
float2 TexCoordA : TEXCOORD5;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constants
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
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)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Funcions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Bloom Vertex Shader
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
uniform float2 ScreenDims;
|
||||
|
||||
uniform float2 Prescale = float2(1.0f, 1.0f);
|
||||
uniform float2 TargetDims;
|
||||
|
||||
uniform float4 Level01Size;
|
||||
uniform float4 Level23Size;
|
||||
@ -199,15 +219,16 @@ VS_OUTPUT vs_main(VS_INPUT Input)
|
||||
Output.Color = Input.Color;
|
||||
|
||||
float2 TexCoord = Input.Position.xy / ScreenDims;
|
||||
TexCoord += 0.5f / TargetDims; // half texel offset correction (DX9)
|
||||
|
||||
Output.TexCoord01.xy = TexCoord.xy;
|
||||
Output.TexCoord01.zw = TexCoord.xy + Prescale.xy / Level01Size.zw;
|
||||
Output.TexCoord23 = TexCoord.xyxy + Prescale.xyxy / Level23Size;
|
||||
Output.TexCoord45 = TexCoord.xyxy + Prescale.xyxy / Level45Size;
|
||||
Output.TexCoord67 = TexCoord.xyxy + Prescale.xyxy / Level67Size;
|
||||
Output.TexCoord89 = TexCoord.xyxy + Prescale.xyxy / Level89Size;
|
||||
Output.TexCoordA = TexCoord.xy + Prescale.xy / LevelASize;
|
||||
|
||||
Output.TexCoord01.zw = TexCoord.xy + 0.5f / Level01Size.zw;
|
||||
Output.TexCoord23 = TexCoord.xyxy + 0.5f / Level23Size;
|
||||
Output.TexCoord45 = TexCoord.xyxy + 0.5f / Level45Size;
|
||||
Output.TexCoord67 = TexCoord.xyxy + 0.5f / Level67Size;
|
||||
Output.TexCoord89 = TexCoord.xyxy + 0.5f / Level89Size;
|
||||
Output.TexCoordA = TexCoord.xy + 0.5f / LevelASize;
|
||||
|
||||
return Output;
|
||||
}
|
||||
|
||||
@ -219,6 +240,12 @@ uniform float4 Level0123Weight;
|
||||
uniform float4 Level4567Weight;
|
||||
uniform float3 Level89AWeight;
|
||||
|
||||
float3 GetNoiseFactor(float3 n, float random)
|
||||
{
|
||||
// smaller n become more noisy
|
||||
return 1.0f + random * max(0.0f, 0.25f * pow(E, -8 * n));
|
||||
}
|
||||
|
||||
float4 ps_main(PS_INPUT Input) : COLOR
|
||||
{
|
||||
float3 texel0 = tex2D(DiffuseSampler0, Input.TexCoord01.xy).rgb;
|
||||
@ -245,19 +272,22 @@ float4 ps_main(PS_INPUT Input) : COLOR
|
||||
texel9 = texel9 * Level89AWeight.y;
|
||||
texelA = texelA * Level89AWeight.z;
|
||||
|
||||
float4 sum = float4(
|
||||
texel0 +
|
||||
texel1 +
|
||||
texel2 +
|
||||
texel3 +
|
||||
float3 bloom = float3(
|
||||
texel1 +
|
||||
texel2 +
|
||||
texel3 +
|
||||
texel4 +
|
||||
texel5 +
|
||||
texel6 +
|
||||
texel7 +
|
||||
texel8 +
|
||||
texel9 +
|
||||
texelA, 1.0f);
|
||||
return sum;
|
||||
texel5 +
|
||||
texel6 +
|
||||
texel7 +
|
||||
texel8 +
|
||||
texel9 +
|
||||
texelA);
|
||||
|
||||
float2 NoiseCoord = Input.TexCoord01.xy;
|
||||
float3 NoiseFactor = GetNoiseFactor(bloom, random(NoiseCoord));
|
||||
|
||||
return float4(texel0 + bloom * NoiseFactor, 1.0f);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
330
hlsl/distortion.fx
Normal file
330
hlsl/distortion.fx
Normal file
@ -0,0 +1,330 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:ImJezze
|
||||
//-----------------------------------------------------------------------------
|
||||
// Distortion Effect
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constants
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static const float Epsilon = 1.0e-7f;
|
||||
static const float PI = 3.1415927f;
|
||||
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
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool xor(bool a, bool b)
|
||||
{
|
||||
return (a || b) && !(a && b);
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Distortion Vertex Shader
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
uniform float2 ScreenDims; // size of the window or fullscreen
|
||||
uniform float2 TargetDims;
|
||||
uniform float2 QuadDims; // size of the screen quad
|
||||
|
||||
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
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
uniform float2 DefaultScreenRatio = float2(1.0f, 3.0f / 4.0f); // normalized screen ratio (defalt ratio of 4:3)
|
||||
|
||||
uniform float CurvatureAmount = 0.0f;
|
||||
uniform float RoundCornerAmount = 0.0f;
|
||||
uniform float SmoothBorderAmount = 0.5f;
|
||||
uniform float VignettingAmount = 0.0f;
|
||||
uniform float ReflectionAmount = 0.0f;
|
||||
|
||||
uniform bool OrientationSwapXY = false; // false landscape, true portrait for default screen orientation
|
||||
uniform bool RotationSwapXY = false; // swapped default screen orientation due to screen rotation
|
||||
uniform int RotationType = 0; // 0 = 0°, 1 = 90°, 2 = 180°, 3 = 270°
|
||||
|
||||
float2 GetRatioCorrecton()
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
float GetNoiseFactor(float3 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 = GetRatioCorrecton();
|
||||
|
||||
float2 defaultScreenRatio = xor(OrientationSwapXY, RotationSwapXY)
|
||||
? DefaultScreenRatio.yx
|
||||
: DefaultScreenRatio.xy;
|
||||
|
||||
// upper right quadrant
|
||||
float2 spotOffset =
|
||||
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);
|
||||
|
||||
float2 SpotCoord = coord;
|
||||
SpotCoord += spotOffset * defaultScreenRatio * 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 = normalizedSigmoid(Spot, 0.75) * amount;
|
||||
|
||||
// increase strength by 100%
|
||||
SigmoidSpot = SigmoidSpot * 2.0f;
|
||||
|
||||
return saturate(SigmoidSpot);
|
||||
}
|
||||
|
||||
float GetRoundCornerFactor(float2 coord, float radiusAmount, float smoothAmount)
|
||||
{
|
||||
float2 RatioCorrection = GetRatioCorrecton();
|
||||
|
||||
smoothAmount = min(smoothAmount, radiusAmount);
|
||||
|
||||
float2 RoundCornerCoord = coord * 2;
|
||||
|
||||
float MinScreenDims = min(ScreenDims.x, ScreenDims.y);
|
||||
|
||||
float radius = MinScreenDims * 0.5 * max(radiusAmount, 0.01f);
|
||||
float smooth = 1.0 / (MinScreenDims * 0.25 * max(smoothAmount, 0.01f));
|
||||
|
||||
// compute box
|
||||
float box = roundBox(ScreenDims * RoundCornerCoord, ScreenDims * 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 coord, float amount)
|
||||
{
|
||||
amount *= 0.25f; // reduced amount
|
||||
|
||||
float2 RatioCorrection = GetRatioCorrecton();
|
||||
|
||||
// center coordinates
|
||||
coord -= 0.5f;
|
||||
|
||||
coord /= RatioCorrection;
|
||||
|
||||
// lens distortion coefficient
|
||||
float k = amount;
|
||||
|
||||
// cubic distortion value
|
||||
float kcube = amount * 2.0f;
|
||||
|
||||
// compute cubic distortion factor
|
||||
float r2 = coord.x * coord.x + coord.y * coord.y;
|
||||
float f = kcube == 0.0f
|
||||
? 1 + r2 * k
|
||||
: 1 + r2 * (k + kcube * sqrt(r2));
|
||||
|
||||
// correct zoom
|
||||
f /= 1.0f + amount * 0.5f;
|
||||
|
||||
// apply cubic distortion factor
|
||||
coord *= f;
|
||||
|
||||
coord *= RatioCorrection;
|
||||
|
||||
// uncenter coordinates
|
||||
coord += 0.5f;
|
||||
|
||||
return coord;
|
||||
}
|
||||
|
||||
float4 ps_main(PS_INPUT Input) : COLOR
|
||||
{
|
||||
float2 TexCoord = Input.TexCoord;
|
||||
float2 BaseCoord = TexCoord;
|
||||
|
||||
// // test code
|
||||
// // BaseCoord.x += (TexCoord.x > 0.5f ? -0.5f : 0.0f);
|
||||
// BaseCoord.y += (TexCoord.y > 0.5f ? -0.5f : 0.0f);
|
||||
// BaseCoord.y *= 2.0f;
|
||||
|
||||
// Screen Curvature
|
||||
BaseCoord = GetDistortedCoords(BaseCoord, CurvatureAmount);
|
||||
|
||||
float2 BaseCoordCentered = BaseCoord;
|
||||
BaseCoordCentered -= 0.5f;
|
||||
|
||||
// // test code
|
||||
// BaseCoord.y /= 2.0f;
|
||||
// // BaseCoord.x += (TexCoord.x > 0.5f ? +0.5f : 0.0f);
|
||||
// BaseCoord.y += (TexCoord.y > 0.5 ? +0.5f : 0.0f);
|
||||
|
||||
float2 defaultScreenRatio = xor(OrientationSwapXY, RotationSwapXY)
|
||||
? DefaultScreenRatio.yx
|
||||
: DefaultScreenRatio.xy;
|
||||
|
||||
float2 BaseRatioCoordCentered = BaseCoordCentered;
|
||||
BaseRatioCoordCentered *= defaultScreenRatio;
|
||||
|
||||
// Color
|
||||
float4 BaseColor = tex2D(DiffuseSampler, BaseCoord);
|
||||
BaseColor.a = 1.0f;
|
||||
|
||||
// Vignetting Simulation
|
||||
float2 VignetteCoord = BaseCoordCentered;
|
||||
|
||||
float VignetteFactor = GetVignetteFactor(VignetteCoord, VignettingAmount);
|
||||
BaseColor.rgb *= VignetteFactor;
|
||||
|
||||
// Light Reflection Simulation
|
||||
float3 LightColor = float3(1.0f, 0.90f, 0.80f);
|
||||
|
||||
float2 SpotCoord = BaseRatioCoordCentered;
|
||||
float2 NoiseCoord = BaseRatioCoordCentered;
|
||||
|
||||
float SpotAddend = GetSpotAddend(SpotCoord, ReflectionAmount);
|
||||
float NoiseFactor = GetNoiseFactor(SpotAddend, random(NoiseCoord));
|
||||
BaseColor.rgb += SpotAddend * NoiseFactor * LightColor;
|
||||
|
||||
// Round Corners Simulation
|
||||
float2 RoundCornerCoord = BaseCoordCentered;
|
||||
|
||||
float roundCornerFactor = GetRoundCornerFactor(RoundCornerCoord, RoundCornerAmount, 0);
|
||||
BaseColor.rgb *= roundCornerFactor;
|
||||
|
||||
// // test code
|
||||
// BaseColor.rgb = BaseCoord.x * BaseCoord.y;
|
||||
// BaseColor.rgb = TexCoord.y > 0.5f ? 1.0f : 0.5f;
|
||||
|
||||
return BaseColor;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Distortion Effect
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
technique DistortionTechnique
|
||||
{
|
||||
pass Pass0
|
||||
{
|
||||
Lighting = FALSE;
|
||||
|
||||
VertexShader = compile vs_3_0 vs_main();
|
||||
PixelShader = compile ps_3_0 ps_main();
|
||||
}
|
||||
}
|
@ -48,15 +48,15 @@ struct PS_INPUT
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
uniform float2 ScreenDims;
|
||||
uniform float2 TargetSize;
|
||||
uniform float2 TargetDims;
|
||||
|
||||
uniform float2 Prescale = float2(1.0f, 1.0f);
|
||||
uniform bool PrepareVector;
|
||||
|
||||
VS_OUTPUT vs_main(VS_INPUT Input)
|
||||
{
|
||||
VS_OUTPUT Output = (VS_OUTPUT)0;
|
||||
|
||||
float2 TargetTexelSize = 1.0f / TargetSize;
|
||||
float2 TargetTexelDims = 1.0f / TargetDims;
|
||||
|
||||
Output.Position = float4(Input.Position.xyz, 1.0f);
|
||||
Output.Position.xy /= ScreenDims;
|
||||
@ -67,11 +67,14 @@ VS_OUTPUT vs_main(VS_INPUT Input)
|
||||
Output.Color = Input.Color;
|
||||
|
||||
float2 TexCoord = Input.Position.xy / ScreenDims;
|
||||
TexCoord += PrepareVector
|
||||
? 0.5f / TargetDims // half texel offset correction (DX9)
|
||||
: 0.0f;
|
||||
|
||||
Output.TexCoord01.xy = TexCoord + float2(-0.5f, -0.5f) * TargetTexelSize * Prescale;
|
||||
Output.TexCoord01.zw = TexCoord + float2( 0.5f, -0.5f) * TargetTexelSize * Prescale;
|
||||
Output.TexCoord23.xy = TexCoord + float2(-0.5f, 0.5f) * TargetTexelSize * Prescale;
|
||||
Output.TexCoord23.zw = TexCoord + float2( 0.5f, 0.5f) * TargetTexelSize * Prescale;
|
||||
Output.TexCoord01.xy = TexCoord + float2(-0.5f, -0.5f) * TargetTexelDims;
|
||||
Output.TexCoord01.zw = TexCoord + float2( 0.5f, -0.5f) * TargetTexelDims;
|
||||
Output.TexCoord23.xy = TexCoord + float2(-0.5f, 0.5f) * TargetTexelDims;
|
||||
Output.TexCoord23.zw = TexCoord + float2( 0.5f, 0.5f) * TargetTexelDims;
|
||||
|
||||
return Output;
|
||||
}
|
||||
|
@ -83,8 +83,9 @@ VS_OUTPUT vs_main(VS_INPUT Input)
|
||||
Output.Position.y = 1.0f - Output.Position.y; // flip y
|
||||
Output.Position.xy -= 0.5f; // center
|
||||
Output.Position.xy *= 2.0f; // zoom
|
||||
|
||||
float2 TexCoord = Input.TexCoord + 0.5f / TargetDims;
|
||||
|
||||
float2 TexCoord = Input.TexCoord;
|
||||
TexCoord += 0.5f / TargetDims; // half texel offset correction (DX9)
|
||||
|
||||
Output.TexCoord0 = TexCoord;
|
||||
Output.TexCoord1 = TexCoord + Coord1Offset * TargetTexelDims * Defocus;
|
||||
@ -117,7 +118,7 @@ float4 ps_main(PS_INPUT Input) : COLOR
|
||||
|
||||
float3 blurred = (d0.rgb + d1 + d2 + d3 + d4 + d5 + d6 + d7) / 8.0f;
|
||||
blurred = lerp(d0.rgb, blurred, 1.0f);
|
||||
|
||||
|
||||
return float4(blurred, d0.a);
|
||||
}
|
||||
|
||||
|
@ -68,18 +68,20 @@ uniform bool Passthrough;
|
||||
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.TexCoord = Input.TexCoord + 0.5f / TargetDims;
|
||||
|
||||
Output.TexCoord = Input.TexCoord;
|
||||
Output.TexCoord += 0.5f / TargetDims; // half texel offset correction (DX9)
|
||||
|
||||
Output.PrevCoord = Output.TexCoord;
|
||||
|
||||
Output.Color = Input.Color;
|
||||
|
||||
|
||||
return Output;
|
||||
}
|
||||
|
||||
@ -93,13 +95,13 @@ float4 ps_main(PS_INPUT Input) : COLOR
|
||||
{
|
||||
float4 CurrPix = tex2D(DiffuseSampler, Input.TexCoord);
|
||||
float3 PrevPix = tex2D(PreviousSampler, Input.PrevCoord).rgb * float3(Phosphor.r, Phosphor.g, Phosphor.b);
|
||||
|
||||
|
||||
float RedMax = max(CurrPix.r, PrevPix.r);
|
||||
float GreenMax = max(CurrPix.g, PrevPix.g);
|
||||
float BlueMax = max(CurrPix.b, PrevPix.b);
|
||||
|
||||
return Passthrough
|
||||
? CurrPix
|
||||
? CurrPix
|
||||
: float4(RedMax, GreenMax, BlueMax, CurrPix.a);
|
||||
}
|
||||
|
||||
|
245
hlsl/post.fx
245
hlsl/post.fx
@ -66,22 +66,16 @@ bool xor(bool a, bool b)
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
uniform float2 ScreenDims; // size of the window or fullscreen
|
||||
uniform float2 ScreenRatio = float2(1.0f, 3.0f / 4.0f); // normalized screen ratio (defalt ratio of 4:3)
|
||||
|
||||
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 target
|
||||
uniform float2 TargetDims; // size of the target surface
|
||||
|
||||
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 float2 Prescale = float2(8.0f, 8.0f);
|
||||
|
||||
uniform bool OrientationSwapXY = false; // false landscape, true portrait for default screen orientation
|
||||
uniform bool RotationSwapXY = false; // swapped default screen orientation due to screen rotation
|
||||
|
||||
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;
|
||||
|
||||
VS_OUTPUT vs_main(VS_INPUT Input)
|
||||
@ -93,12 +87,11 @@ VS_OUTPUT vs_main(VS_INPUT Input)
|
||||
? shadowUVOffset.yx
|
||||
: shadowUVOffset.xy;
|
||||
|
||||
// todo: calculate offset
|
||||
float2 ScreenCoordPrescaleOffset = 0.0f;
|
||||
ScreenCoordPrescaleOffset += shadowUVOffset;
|
||||
float2 ScreenCoordOffset = 0.0f;
|
||||
ScreenCoordOffset += shadowUVOffset;
|
||||
|
||||
Output.ScreenCoord = Input.Position.xy;
|
||||
Output.ScreenCoord += ScreenCoordPrescaleOffset;
|
||||
Output.ScreenCoord += ScreenCoordOffset;
|
||||
|
||||
Output.Position = float4(Input.Position.xyz, 1.0f);
|
||||
Output.Position.xy /= ScreenDims;
|
||||
@ -108,7 +101,8 @@ VS_OUTPUT vs_main(VS_INPUT Input)
|
||||
|
||||
Output.TexCoord = PrepareVector
|
||||
? Input.Position.xy / ScreenDims
|
||||
: Input.TexCoord; // + 0.5f / TargetDims;
|
||||
: Input.TexCoord;
|
||||
Output.TexCoord += 0.5f / TargetDims; // half texel offset correction (DX9)
|
||||
|
||||
Output.Color = Input.Color;
|
||||
|
||||
@ -126,11 +120,6 @@ uniform float ScanlineBrightOffset = 1.0f;
|
||||
uniform float ScanlineOffset = 1.0f;
|
||||
uniform float ScanlineHeight = 1.0f;
|
||||
|
||||
uniform float CurvatureAmount = 0.0f;
|
||||
uniform float RoundCornerAmount = 0.0f;
|
||||
uniform float VignettingAmount = 0.0f;
|
||||
uniform float ReflectionAmount = 0.0f;
|
||||
|
||||
uniform float ShadowAlpha = 0.0f;
|
||||
uniform float2 ShadowCount = float2(6.0f, 6.0f);
|
||||
uniform float2 ShadowUV = float2(0.25f, 0.25f);
|
||||
@ -138,198 +127,18 @@ 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);
|
||||
|
||||
static const float Epsilon = 1.0e-7f;
|
||||
static const float PI = 3.1415927f;
|
||||
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)
|
||||
|
||||
float nextPowerOfTwo(float n)
|
||||
{
|
||||
return pow(2, floor(log2(n) / log2(2)) + 1);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
float GetNoiseFactor(float n, float random)
|
||||
{
|
||||
// smaller n become more noisy
|
||||
return 1.0f + random * max(0.0f, 0.25f * pow(E, -4 * 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 SpotCoord = coord;
|
||||
SpotCoord += OrientationSwapXY
|
||||
? float2(-0.25f, -0.25f) * ScreenRatio // upper right quadrant
|
||||
: float2(-0.25f, 0.25f) * ScreenRatio; // upper right quadrant
|
||||
|
||||
float SpotBlur = amount;
|
||||
|
||||
// 0.5 full screen fitting circle
|
||||
float SpotRadius = amount * 0.75f;
|
||||
float Spot = smoothstep(SpotRadius, SpotRadius - SpotBlur, length(SpotCoord));
|
||||
|
||||
float SigmoidSpot = normalizedSigmoid(Spot, 0.75) * amount;
|
||||
|
||||
// increase strength by 100%
|
||||
SigmoidSpot = SigmoidSpot * 2.0f;
|
||||
|
||||
return saturate(SigmoidSpot);
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
float GetRoundCornerFactor(float2 coord, float amount)
|
||||
{
|
||||
// hint: vector target area is always quadratic
|
||||
float2 UsedSourceRect = PrepareVector
|
||||
? float2(1.0f, 1.0f)
|
||||
: SourceRect;
|
||||
float2 SourceArea = 1.0f / UsedSourceRect;
|
||||
float2 SourceDimsArea = SourceDims * UsedSourceRect;
|
||||
float2 SourceRatio = float2(1.0f, SourceDimsArea.y / SourceDimsArea.x);
|
||||
float2 SourceTexelDims = 1.0f / SourceDims;
|
||||
|
||||
// base on the default ratio of 4:3
|
||||
float2 RoundCoordScale = (SourceDims / SourceArea / SourceRatio) * ScreenRatio;
|
||||
|
||||
float2 RoundCoord = coord;
|
||||
// hint: alignment correction
|
||||
RoundCoord -= SourceTexelDims * SourceArea;
|
||||
RoundCoord *= SourceTexelDims * SourceArea + 1.0f;
|
||||
// hint: roundness correction
|
||||
RoundCoord *= RoundCoordScale;
|
||||
|
||||
float radius = amount * 50.0f;
|
||||
|
||||
// compute box (base on the default ratio of 4:3)
|
||||
float box = RoundBox(RoundCoord.xy, (RoundCoordScale * 0.5f), radius);
|
||||
|
||||
// // apply blur
|
||||
// float blurAmount = 1.0f / max(1.0f, amount * 25.0f);
|
||||
// float blueOffset = 1.0f - pow(blurAmount * 0.5f, 0.5f);
|
||||
// box *= blurAmount;
|
||||
// box += blueOffset;
|
||||
|
||||
float border = smoothstep(1.0f, 0.5f, box);
|
||||
|
||||
return saturate(border);
|
||||
}
|
||||
|
||||
float4 ps_main(PS_INPUT Input) : COLOR
|
||||
{
|
||||
float2 ScreenTexelDims = 1.0f / ScreenDims;
|
||||
float2 SourceTexelDims = 1.0f / SourceDims;
|
||||
|
||||
// hint: vector target area is always quadratic
|
||||
float2 UsedSourceRect = PrepareVector
|
||||
? float2(1.0f, 1.0f)
|
||||
: SourceRect;
|
||||
float UsedCurvatureAmount = CurvatureAmount * 0.25f; // reduced curvature
|
||||
|
||||
float2 SourceArea = 1.0f / UsedSourceRect;
|
||||
float2 DoubleSourceArea = SourceArea * 2.0f;
|
||||
float SquareSourceAreaLength = pow(length(SourceArea), 2.0f);
|
||||
float2 HalfSourceRect = UsedSourceRect * 0.5f;
|
||||
|
||||
// Screen Curvature
|
||||
float2 CurvatureUnitCoord = (Input.TexCoord * DoubleSourceArea) - 1.0f;
|
||||
float2 CurvatureFactor = (1.0 / SquareSourceAreaLength) * UsedCurvatureAmount;
|
||||
float2 CurvatureCurve = CurvatureUnitCoord * pow(length(CurvatureUnitCoord), 2.0f) * CurvatureFactor;
|
||||
float2 CurvatureZoom = 1.0f - (DoubleSourceArea * CurvatureFactor);
|
||||
|
||||
// todo: vector cuverture requires a correction on y-axis if screen and target size differ and y > x
|
||||
|
||||
float2 ScreenCoord = Input.ScreenCoord / ScreenDims;
|
||||
ScreenCoord -= HalfSourceRect;
|
||||
ScreenCoord *= CurvatureZoom; // zoom
|
||||
ScreenCoord += HalfSourceRect;
|
||||
ScreenCoord += CurvatureCurve; // distortion
|
||||
|
||||
float2 BaseCoord = Input.TexCoord;
|
||||
BaseCoord -= HalfSourceRect;
|
||||
BaseCoord *= CurvatureZoom; // zoom
|
||||
BaseCoord += HalfSourceRect;
|
||||
BaseCoord += CurvatureCurve; // distortion
|
||||
|
||||
float2 CurvatureCorrection = 1.0f;
|
||||
|
||||
// vector cuverture correction
|
||||
if (PrepareVector)
|
||||
{
|
||||
float ScreenRatio = ScreenDims.x / ScreenDims.y;
|
||||
float TargetRatio = TargetDims.x / TargetDims.y;
|
||||
|
||||
// hint: vector cuverture requires a correction on the x-axis by the amount that screen and target size differ
|
||||
CurvatureCorrection.x +=
|
||||
(ScreenRatio / TargetRatio - 1.0f)
|
||||
* (1.0f + SquareSourceAreaLength * UsedCurvatureAmount);
|
||||
}
|
||||
|
||||
// the floowing coordinates are used for effects
|
||||
float2 BaseCoordCentered = Input.TexCoord;
|
||||
BaseCoordCentered -= HalfSourceRect;
|
||||
BaseCoordCentered *= CurvatureZoom * CurvatureCorrection; // zoom
|
||||
BaseCoordCentered += CurvatureCurve * CurvatureCorrection; // distortion
|
||||
|
||||
float2 BaseAreaCoord = BaseCoord;
|
||||
BaseAreaCoord *= SourceArea;
|
||||
|
||||
float2 BaseAreaCoordCentered = BaseCoordCentered;
|
||||
BaseAreaCoordCentered *= SourceArea;
|
||||
|
||||
float2 BaseAreaRatioCoord = BaseAreaCoord;
|
||||
BaseAreaRatioCoord *= ScreenRatio;
|
||||
|
||||
float2 BaseAreaRatioCoordCentered = BaseAreaCoordCentered;
|
||||
BaseAreaRatioCoordCentered *= ScreenRatio;
|
||||
|
||||
// // Alpha Clipping (round corners applies smoother clipping when screen is curved)
|
||||
// clip((BaseCoord < SourceTexelDims) ? -1 : 1);
|
||||
// clip((BaseCoord > SourceRect + SourceTexelDims) ? -1 : 1);
|
||||
|
||||
// Color
|
||||
float4 BaseColor = tex2D(DiffuseSampler, BaseCoord);
|
||||
BaseColor.a = 1.0f;
|
||||
// BaseColor.rgb = 1.0f;
|
||||
|
||||
// Vignetting Simulation (may affect bloom)
|
||||
float2 VignetteCoord = BaseAreaCoordCentered;
|
||||
|
||||
float VignetteFactor = GetVignetteFactor(VignetteCoord, VignettingAmount);
|
||||
BaseColor.rgb *= VignetteFactor;
|
||||
|
||||
// Mask Simulation (may not affect bloom)
|
||||
if (!PrepareBloom)
|
||||
@ -387,15 +196,16 @@ float4 ps_main(PS_INPUT Input) : COLOR
|
||||
// Scanline Simulation (may not affect bloom)
|
||||
if (!PrepareBloom)
|
||||
{
|
||||
// todo: there is an offset which can be noticed at lower prescale in high-resolution
|
||||
float2 ScanlinePrescaleOffset = 0.0f;
|
||||
// Scanline Simulation (disabled for vector)
|
||||
if (!PrepareVector)
|
||||
{
|
||||
float InnerSine = BaseCoord.y * ScanlineScale * SourceDims.y;
|
||||
float ScanJitter = ScanlineOffset * SourceDims.y;
|
||||
float ScanBrightMod = sin(InnerSine * PI + ScanJitter);
|
||||
float3 ScanColor = lerp(1.0f, (pow(ScanBrightMod * ScanBrightMod, ScanlineHeight) * ScanlineBrightScale + 1.0f + ScanlineBrightOffset) * 0.5f, ScanlineAlpha);
|
||||
|
||||
float InnerSine = BaseCoord.y * ScanlineScale * SourceDims.y;
|
||||
float ScanJitter = ScanlineOffset * SourceDims.y;
|
||||
float ScanBrightMod = sin(InnerSine * PI + ScanJitter + ScanlinePrescaleOffset);
|
||||
float3 ScanColor = lerp(1.0f, (pow(ScanBrightMod * ScanBrightMod, ScanlineHeight) * ScanlineBrightScale + 1.0f + ScanlineBrightOffset) * 0.5f, ScanlineAlpha);
|
||||
|
||||
BaseColor.rgb *= ScanColor;
|
||||
BaseColor.rgb *= ScanColor;
|
||||
}
|
||||
}
|
||||
|
||||
// Output
|
||||
@ -404,25 +214,6 @@ float4 ps_main(PS_INPUT Input) : COLOR
|
||||
: BaseColor * Input.Color;
|
||||
Output.a = 1.0f;
|
||||
|
||||
// Light Reflection Simulation (may not affect bloom)
|
||||
if (!PrepareBloom)
|
||||
{
|
||||
float3 LightColor = float3(1.0f, 0.90f, 0.80f);
|
||||
|
||||
float2 SpotCoord = BaseAreaRatioCoordCentered;
|
||||
float2 NoiseCoord = BaseAreaRatioCoordCentered;
|
||||
|
||||
float SpotAddend = GetSpotAddend(SpotCoord, ReflectionAmount);
|
||||
float NoiseFactor = GetNoiseFactor(SpotAddend, random(NoiseCoord));
|
||||
Output.rgb += SpotAddend * NoiseFactor * LightColor;
|
||||
}
|
||||
|
||||
// Round Corners Simulation (may affect bloom)
|
||||
float2 RoundCornerCoord = BaseAreaCoordCentered;
|
||||
|
||||
float roundCornerFactor = GetRoundCornerFactor(RoundCornerCoord, RoundCornerAmount);
|
||||
Output.rgb *= roundCornerFactor;
|
||||
|
||||
return Output;
|
||||
}
|
||||
|
||||
@ -436,7 +227,7 @@ technique ScanMaskTechnique
|
||||
{
|
||||
Lighting = FALSE;
|
||||
|
||||
//Sampler[0] = <DiffuseSampler>;
|
||||
Sampler[0] = <DiffuseSampler>;
|
||||
|
||||
VertexShader = compile vs_3_0 vs_main();
|
||||
PixelShader = compile ps_3_0 ps_main();
|
||||
|
@ -45,24 +45,33 @@ struct PS_INPUT
|
||||
// Simple Vertex Shader
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static const float Epsilon = 1.0e-7f;
|
||||
|
||||
uniform float2 ScreenDims;
|
||||
uniform float2 TargetDims;
|
||||
|
||||
uniform bool PostPass;
|
||||
|
||||
uniform float Brighten;
|
||||
|
||||
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.TexCoord = PostPass
|
||||
float2 targetDims = TargetDims + Epsilon; // bug: with exact target dimensions the font disappears
|
||||
|
||||
Output.TexCoord = PostPass
|
||||
? Input.Position.xy / ScreenDims
|
||||
: Input.TexCoord;
|
||||
Output.TexCoord += PostPass
|
||||
? 0.5f / targetDims // half texel offset correction (DX9)
|
||||
: 0.0f;
|
||||
|
||||
Output.Color = Input.Color;
|
||||
|
||||
@ -76,7 +85,9 @@ VS_OUTPUT vs_main(VS_INPUT Input)
|
||||
float4 ps_main(PS_INPUT Input) : COLOR
|
||||
{
|
||||
float4 BaseTexel = tex2D(DiffuseSampler, Input.TexCoord);
|
||||
return BaseTexel * (Input.Color + float4(Brighten, Brighten, Brighten, 0.0f));
|
||||
BaseTexel *= Input.Color + float4(Brighten, Brighten, Brighten, 0.0f);
|
||||
|
||||
return BaseTexel;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -605,6 +605,7 @@ public:
|
||||
float max_update_rate() const { return m_max_refresh; }
|
||||
int orientation() const { return m_orientation; }
|
||||
render_layer_config layer_config() const { return m_layerconfig; }
|
||||
layout_view *current_view() const { return m_curview; }
|
||||
int view() const { return view_index(*m_curview); }
|
||||
bool hidden() const { return ((m_flags & RENDER_CREATE_HIDDEN) != 0); }
|
||||
bool is_ui_target() const;
|
||||
|
@ -235,6 +235,8 @@ public:
|
||||
layout_view *next() const { return m_next; }
|
||||
item *first_item(item_layer layer) const;
|
||||
const char *name() const { return m_name.c_str(); }
|
||||
const render_bounds &bounds() const { return m_bounds; }
|
||||
const render_bounds &screen_bounds() const { return m_scrbounds; }
|
||||
const render_screen_list &screens() const { return m_screens; }
|
||||
bool layer_enabled(item_layer layer) const { return m_layenabled[layer]; }
|
||||
|
||||
|
@ -989,6 +989,7 @@ int shaders::create_resources(bool reset)
|
||||
|
||||
default_effect = new effect(this, d3d->get_device(), "primary.fx", fx_dir);
|
||||
post_effect = new effect(this, d3d->get_device(), "post.fx", fx_dir);
|
||||
distortion_effect = new effect(this, d3d->get_device(), "distortion.fx", fx_dir);
|
||||
prescale_effect = new effect(this, d3d->get_device(), "prescale.fx", fx_dir);
|
||||
phosphor_effect = new effect(this, d3d->get_device(), "phosphor.fx", fx_dir);
|
||||
focus_effect = new effect(this, d3d->get_device(), "focus.fx", fx_dir);
|
||||
@ -1002,6 +1003,7 @@ int shaders::create_resources(bool reset)
|
||||
|
||||
if (!default_effect->is_valid() ||
|
||||
!post_effect->is_valid() ||
|
||||
!distortion_effect->is_valid() ||
|
||||
!prescale_effect->is_valid() ||
|
||||
!phosphor_effect->is_valid() ||
|
||||
!focus_effect->is_valid() ||
|
||||
@ -1076,15 +1078,11 @@ int shaders::create_resources(bool reset)
|
||||
downsample_effect->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS);
|
||||
|
||||
bloom_effect->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS);
|
||||
bloom_effect->add_uniform("TargetDims", uniform::UT_VEC2, uniform::CU_TARGET_DIMS);
|
||||
|
||||
post_effect->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS);
|
||||
post_effect->add_uniform("SourceRect", uniform::UT_VEC2, uniform::CU_SOURCE_RECT);
|
||||
post_effect->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS);
|
||||
|
||||
post_effect->add_uniform("VignettingAmount", uniform::UT_FLOAT, uniform::CU_POST_VIGNETTING);
|
||||
post_effect->add_uniform("CurvatureAmount", uniform::UT_FLOAT, uniform::CU_POST_CURVATURE);
|
||||
post_effect->add_uniform("RoundCornerAmount", uniform::UT_FLOAT, uniform::CU_POST_ROUND_CORNER);
|
||||
post_effect->add_uniform("ReflectionAmount", uniform::UT_FLOAT, uniform::CU_POST_REFLECTION);
|
||||
post_effect->add_uniform("TargetDims", uniform::UT_VEC2, uniform::CU_TARGET_DIMS);
|
||||
|
||||
post_effect->add_uniform("ShadowAlpha", uniform::UT_FLOAT, uniform::CU_POST_SHADOW_ALPHA);
|
||||
post_effect->add_uniform("ShadowCount", uniform::UT_VEC2, uniform::CU_POST_SHADOW_COUNT);
|
||||
@ -1100,9 +1098,19 @@ int shaders::create_resources(bool reset)
|
||||
post_effect->add_uniform("Power", uniform::UT_VEC3, uniform::CU_POST_POWER);
|
||||
post_effect->add_uniform("Floor", uniform::UT_VEC3, uniform::CU_POST_FLOOR);
|
||||
|
||||
distortion_effect->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS);
|
||||
distortion_effect->add_uniform("TargetDims", uniform::UT_VEC2, uniform::CU_TARGET_DIMS);
|
||||
distortion_effect->add_uniform("QuadDims", uniform::UT_VEC2, uniform::CU_QUAD_DIMS);
|
||||
|
||||
distortion_effect->add_uniform("VignettingAmount", uniform::UT_FLOAT, uniform::CU_POST_VIGNETTING);
|
||||
distortion_effect->add_uniform("CurvatureAmount", uniform::UT_FLOAT, uniform::CU_POST_CURVATURE);
|
||||
distortion_effect->add_uniform("RoundCornerAmount", uniform::UT_FLOAT, uniform::CU_POST_ROUND_CORNER);
|
||||
distortion_effect->add_uniform("ReflectionAmount", uniform::UT_FLOAT, uniform::CU_POST_REFLECTION);
|
||||
|
||||
vector_effect->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS);
|
||||
|
||||
default_effect->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS);
|
||||
default_effect->add_uniform("TargetDims", uniform::UT_VEC2, uniform::CU_TARGET_DIMS);
|
||||
|
||||
initialized = true;
|
||||
|
||||
@ -1125,6 +1133,7 @@ void shaders::begin_draw()
|
||||
|
||||
default_effect->set_technique("TestTechnique");
|
||||
post_effect->set_technique("ScanMaskTechnique");
|
||||
distortion_effect->set_technique("DistortionTechnique");
|
||||
phosphor_effect->set_technique("TestTechnique");
|
||||
focus_effect->set_technique("TestTechnique");
|
||||
deconverge_effect->set_technique("DeconvergeTechnique");
|
||||
@ -1187,14 +1196,14 @@ void shaders::blit(
|
||||
for (UINT pass = 0; pass < num_passes; pass++)
|
||||
{
|
||||
curr_effect->begin_pass(pass);
|
||||
|
||||
|
||||
// add the primitives
|
||||
result = (*d3dintf->device.draw_primitive)(d3d->get_device(), prim_type, prim_index, prim_count);
|
||||
if (result != D3D_OK)
|
||||
if (result != D3D_OK)
|
||||
{
|
||||
osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result);
|
||||
}
|
||||
|
||||
|
||||
curr_effect->end_pass();
|
||||
}
|
||||
|
||||
@ -1311,7 +1320,7 @@ int shaders::ntsc_pass(render_target *rt, int source_index, poly_info *poly, int
|
||||
// Convert our signal into YIQ
|
||||
curr_effect = yiq_encode_effect;
|
||||
curr_effect->update_uniforms();
|
||||
|
||||
|
||||
// initial "Diffuse" texture is set in shaders::set_texture()
|
||||
|
||||
next_index = rt->next_index(next_index);
|
||||
@ -1325,7 +1334,7 @@ int shaders::ntsc_pass(render_target *rt, int source_index, poly_info *poly, int
|
||||
|
||||
next_index = rt->next_index(next_index);
|
||||
blit(rt->native_target[next_index], true, D3DPT_TRIANGLELIST, 0, 2);
|
||||
|
||||
|
||||
color_effect->set_texture("Diffuse", rt->native_texture[next_index]);
|
||||
|
||||
return next_index;
|
||||
@ -1337,7 +1346,7 @@ int shaders::color_convolution_pass(render_target *rt, int source_index, poly_in
|
||||
|
||||
curr_effect = color_effect;
|
||||
curr_effect->update_uniforms();
|
||||
|
||||
|
||||
// initial "Diffuse" texture is set in shaders::set_texture() or the result of shaders::ntsc_pass()
|
||||
|
||||
next_index = rt->next_index(next_index);
|
||||
@ -1380,9 +1389,9 @@ int shaders::defocus_pass(render_target *rt, int source_index, poly_info *poly,
|
||||
|
||||
float defocus_x = options->defocus[0];
|
||||
float defocus_y = options->defocus[1];
|
||||
bool focus_enable = defocus_x != 0.0f || defocus_y != 0.0f;
|
||||
|
||||
if (!focus_enable)
|
||||
// skip defocus if no influencing settings
|
||||
if (defocus_x == 0.0f && defocus_y == 0.0f)
|
||||
{
|
||||
return next_index;
|
||||
}
|
||||
@ -1409,7 +1418,7 @@ int shaders::phosphor_pass(render_target *rt, cache_target *ct, int source_index
|
||||
|
||||
next_index = rt->next_index(next_index);
|
||||
blit(rt->prescale_target[next_index], true, D3DPT_TRIANGLELIST, 0, 2);
|
||||
|
||||
|
||||
// Pass along our phosphor'd screen
|
||||
curr_effect->update_uniforms();
|
||||
curr_effect->set_texture("Diffuse", rt->prescale_texture[next_index]);
|
||||
@ -1428,53 +1437,26 @@ int shaders::post_pass(render_target *rt, int source_index, poly_info *poly, int
|
||||
|
||||
texture_info *texture = poly->get_texture();
|
||||
|
||||
bool prepare_vector =
|
||||
bool prepare_vector =
|
||||
PRIMFLAG_GET_VECTORBUF(poly->get_flags()) && vector_enable;
|
||||
float prescale[2] = {
|
||||
prepare_vector ? 1.0f : (float)hlsl_prescale_x,
|
||||
prepare_vector ? 1.0f : (float)hlsl_prescale_y };
|
||||
float target_dims[2] = {
|
||||
poly->get_prim_width(),
|
||||
poly->get_prim_height() };
|
||||
bool orientation_swap_xy =
|
||||
(d3d->window().machine().system().flags & ORIENTATION_SWAP_XY) == ORIENTATION_SWAP_XY;
|
||||
bool rotation_swap_xy =
|
||||
(d3d->window().target()->orientation() & ROT90) == ROT90 ||
|
||||
(d3d->window().target()->orientation() & ROT270) == ROT270;
|
||||
|
||||
|
||||
curr_effect = post_effect;
|
||||
curr_effect->update_uniforms();
|
||||
curr_effect->set_texture("ShadowTexture", shadow_texture == NULL ? NULL : shadow_texture->get_finaltex());
|
||||
curr_effect->set_texture("DiffuseTexture", rt->prescale_texture[next_index]);
|
||||
curr_effect->set_float("ScanlineOffset", texture->get_cur_frame() == 0 ? 0.0f : options->scanline_offset);
|
||||
curr_effect->set_vector("Prescale", 2, prescale);
|
||||
curr_effect->set_vector("TargetDims", 2, target_dims);
|
||||
curr_effect->set_bool("OrientationSwapXY", orientation_swap_xy);
|
||||
curr_effect->set_bool("RotationSwapXY", rotation_swap_xy);
|
||||
curr_effect->set_bool("PrepareBloom", prepare_bloom);
|
||||
curr_effect->set_bool("PrepareVector", prepare_vector);
|
||||
|
||||
if (prepare_vector)
|
||||
{
|
||||
int texture_width = 0;
|
||||
int texture_height = 0;
|
||||
|
||||
texture_info::compute_size_subroutine(d3d->get_texture_manager(), (int)target_dims[0], (int)target_dims[1], &texture_width, &texture_height);
|
||||
|
||||
float source_dims[2] = { (float)texture_width, (float)texture_height };
|
||||
float source_rect[2] = { target_dims[0] / texture_width , target_dims[1] / texture_height };
|
||||
|
||||
// override uniforms
|
||||
curr_effect->set_vector("SourceDims", 2, source_dims);
|
||||
curr_effect->set_vector("SourceRect", 2, source_rect);
|
||||
}
|
||||
|
||||
d3d->set_wrap(D3DTADDRESS_MIRROR);
|
||||
|
||||
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());
|
||||
|
||||
d3d->set_wrap(PRIMFLAG_GET_TEXWRAP(poly->get_texture()->get_flags()) ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP);
|
||||
|
||||
return next_index;
|
||||
}
|
||||
@ -1483,35 +1465,45 @@ int shaders::downsample_pass(render_target *rt, int source_index, poly_info *pol
|
||||
{
|
||||
int next_index = source_index;
|
||||
|
||||
bool prepare_vector =
|
||||
bool prepare_vector =
|
||||
PRIMFLAG_GET_VECTORBUF(poly->get_flags()) && vector_enable;
|
||||
float prescale[2] = {
|
||||
prepare_vector ? 1.0f : (float)hlsl_prescale_x, // no prescale for vector
|
||||
prepare_vector ? 1.0f : (float)hlsl_prescale_y }; // full prescale for raster
|
||||
float bloom_rescale = prepare_vector
|
||||
? options->vector_bloom_scale
|
||||
: options->raster_bloom_scale;
|
||||
|
||||
// skip downsample if no influencing settings
|
||||
if (bloom_rescale == 0.0f)
|
||||
{
|
||||
return next_index;
|
||||
}
|
||||
|
||||
curr_effect = downsample_effect;
|
||||
curr_effect->update_uniforms();
|
||||
curr_effect->set_vector("Prescale", 2, prescale);
|
||||
curr_effect->set_bool("PrepareVector", prepare_vector);
|
||||
|
||||
float bloom_size = (d3d->get_width() < d3d->get_height()) ? d3d->get_width() : d3d->get_height();
|
||||
int bloom_index = 0;
|
||||
float bloom_width = rt->target_width;
|
||||
float bloom_height = rt->target_height;
|
||||
float bloom_size = (d3d->get_width() < d3d->get_height()) ? d3d->get_width() : d3d->get_height();
|
||||
float bloom_width = prepare_vector ? rt->target_width : rt->target_width / hlsl_prescale_x;
|
||||
float bloom_height = prepare_vector ? rt->target_height : rt->target_height / hlsl_prescale_y;
|
||||
for (; bloom_size >= 2.0f && bloom_index < 11; bloom_size *= 0.5f)
|
||||
{
|
||||
bloom_dims[bloom_index][0] = bloom_width;
|
||||
bloom_dims[bloom_index][1] = bloom_height;
|
||||
bloom_dims[bloom_index][0] = (float)(int)bloom_width;
|
||||
bloom_dims[bloom_index][1] = (float)(int)bloom_height;
|
||||
|
||||
curr_effect->set_vector("TargetSize", 2, bloom_dims[bloom_index]);
|
||||
curr_effect->set_texture("DiffuseTexture", (bloom_index == 0) ? rt->native_texture[next_index] : rt->bloom_texture[bloom_index - 1]);
|
||||
curr_effect->set_vector("TargetDims", 2, bloom_dims[bloom_index]);
|
||||
curr_effect->set_texture("DiffuseTexture",
|
||||
bloom_index == 0
|
||||
? rt->native_texture[next_index]
|
||||
: rt->bloom_texture[bloom_index - 1]);
|
||||
|
||||
blit(rt->bloom_target[bloom_index], true, poly->get_type(), vertnum, poly->get_count());
|
||||
|
||||
bloom_index++;
|
||||
bloom_width *= 0.5f;
|
||||
bloom_height *= 0.5f;
|
||||
|
||||
bloom_index++;
|
||||
}
|
||||
|
||||
|
||||
bloom_count = bloom_index;
|
||||
|
||||
return next_index;
|
||||
@ -1521,17 +1513,20 @@ int shaders::bloom_pass(render_target *rt, int source_index, poly_info *poly, in
|
||||
{
|
||||
int next_index = source_index;
|
||||
|
||||
bool prepare_vector = PRIMFLAG_GET_VECTORBUF(poly->get_flags()) && vector_enable;
|
||||
float prescale[2] = {
|
||||
prepare_vector ? 1.0f : (float)hlsl_prescale_x / 2.0f, // no prescale for vector
|
||||
prepare_vector ? 1.0f : (float)hlsl_prescale_y / 2.0f }; // half prescale for raster
|
||||
bool prepare_vector =
|
||||
PRIMFLAG_GET_VECTORBUF(poly->get_flags()) && vector_enable;
|
||||
float bloom_rescale = prepare_vector
|
||||
? options->vector_bloom_scale
|
||||
? options->vector_bloom_scale
|
||||
: options->raster_bloom_scale;
|
||||
|
||||
// skip bloom if no influencing settings
|
||||
if (bloom_rescale == 0.0f)
|
||||
{
|
||||
return next_index;
|
||||
}
|
||||
|
||||
curr_effect = bloom_effect;
|
||||
curr_effect->update_uniforms();
|
||||
curr_effect->set_vector("Prescale", 2, prescale);
|
||||
|
||||
float weight0123[4] = {
|
||||
options->bloom_level0_weight,
|
||||
@ -1545,7 +1540,7 @@ int shaders::bloom_pass(render_target *rt, int source_index, poly_info *poly, in
|
||||
options->bloom_level6_weight * bloom_rescale,
|
||||
options->bloom_level7_weight * bloom_rescale
|
||||
};
|
||||
float weight89A[3] = {
|
||||
float weight89A[3] = {
|
||||
options->bloom_level8_weight * bloom_rescale,
|
||||
options->bloom_level9_weight * bloom_rescale,
|
||||
options->bloom_level10_weight * bloom_rescale
|
||||
@ -1580,8 +1575,102 @@ int shaders::bloom_pass(render_target *rt, int source_index, poly_info *poly, in
|
||||
return next_index;
|
||||
}
|
||||
|
||||
int shaders::distortion_pass(render_target *rt, int source_index, poly_info *poly, int vertnum)
|
||||
{
|
||||
int next_index = source_index;
|
||||
|
||||
int screen_count = d3d->window().target()->current_view()->screens().count();
|
||||
|
||||
// todo: currently only one screen is supported
|
||||
if (screen_count > 1)
|
||||
{
|
||||
return next_index;
|
||||
}
|
||||
|
||||
render_bounds bounds = d3d->window().target()->current_view()->bounds();
|
||||
render_bounds screen_bounds = d3d->window().target()->current_view()->screen_bounds();
|
||||
|
||||
// todo: cuccently artworks are not supported
|
||||
if (bounds.x0 != screen_bounds.x0 ||
|
||||
bounds.y0 != screen_bounds.y0 ||
|
||||
bounds.x1 != screen_bounds.x1 ||
|
||||
bounds.y1 != screen_bounds.y1)
|
||||
{
|
||||
return next_index;
|
||||
}
|
||||
|
||||
// skip distortion if no influencing settings
|
||||
if (options->reflection == 0 &&
|
||||
options->vignetting == 0 &&
|
||||
options->curvature == 0 &&
|
||||
options->round_corner == 0)
|
||||
{
|
||||
return next_index;
|
||||
}
|
||||
|
||||
bool orientation_swap_xy =
|
||||
(d3d->window().machine().system().flags & ORIENTATION_SWAP_XY) == ORIENTATION_SWAP_XY;
|
||||
bool rotation_swap_xy =
|
||||
(d3d->window().target()->orientation() & ROT90) == ROT90 ||
|
||||
(d3d->window().target()->orientation() & ROT270) == ROT270;
|
||||
int rotation_type =
|
||||
(d3d->window().target()->orientation() & ROT90) == ROT90
|
||||
? 1
|
||||
: (d3d->window().target()->orientation() & ROT180) == ROT180
|
||||
? 2
|
||||
: (d3d->window().target()->orientation() & ROT270) == ROT270
|
||||
? 3
|
||||
: 0;
|
||||
|
||||
curr_effect = distortion_effect;
|
||||
curr_effect->update_uniforms();
|
||||
curr_effect->set_texture("DiffuseTexture", rt->prescale_texture[next_index]);
|
||||
curr_effect->set_bool("OrientationSwapXY", orientation_swap_xy);
|
||||
curr_effect->set_bool("RotationSwapXY", rotation_swap_xy);
|
||||
curr_effect->set_int("RotationType", rotation_type);
|
||||
|
||||
next_index = rt->next_index(next_index);
|
||||
blit(rt->prescale_target[next_index], true, poly->get_type(), vertnum, poly->get_count());
|
||||
|
||||
return next_index;
|
||||
}
|
||||
|
||||
int shaders::vector_pass(render_target *rt, int source_index, poly_info *poly, int vertnum)
|
||||
{
|
||||
int next_index = source_index;
|
||||
|
||||
float time_params[2] = { 0.0f, 0.0f };
|
||||
float length_params[3] = { poly->get_line_length(), options->vector_length_scale, options->vector_length_ratio };
|
||||
|
||||
curr_effect = vector_effect;
|
||||
curr_effect->update_uniforms();
|
||||
curr_effect->set_vector("TimeParams", 2, time_params);
|
||||
curr_effect->set_vector("LengthParams", 3, length_params);
|
||||
|
||||
blit(rt->prescale_target[next_index], true, poly->get_type(), vertnum, poly->get_count());
|
||||
|
||||
return next_index;
|
||||
}
|
||||
|
||||
int shaders::vector_buffer_pass(render_target *rt, int source_index, poly_info *poly, int vertnum)
|
||||
{
|
||||
int next_index = source_index;
|
||||
|
||||
curr_effect = default_effect;
|
||||
curr_effect->update_uniforms();
|
||||
|
||||
curr_effect->set_texture("Diffuse", rt->prescale_texture[next_index]);
|
||||
curr_effect->set_bool("PostPass", true);
|
||||
curr_effect->set_float("Brighten", 1.0f);
|
||||
|
||||
next_index = rt->next_index(next_index);
|
||||
blit(rt->prescale_target[next_index], true, poly->get_type(), vertnum, poly->get_count());
|
||||
|
||||
return next_index;
|
||||
}
|
||||
|
||||
int shaders::screen_pass(render_target *rt, int source_index, poly_info *poly, int vertnum)
|
||||
{
|
||||
{
|
||||
int next_index = source_index;
|
||||
|
||||
bool prepare_vector = PRIMFLAG_GET_VECTORBUF(poly->get_flags()) && vector_enable;
|
||||
@ -1611,6 +1700,16 @@ int shaders::screen_pass(render_target *rt, int source_index, poly_info *poly, i
|
||||
return next_index;
|
||||
}
|
||||
|
||||
void shaders::menu_pass(poly_info *poly, int vertnum)
|
||||
{
|
||||
curr_effect = default_effect;
|
||||
curr_effect->update_uniforms();
|
||||
curr_effect->set_bool("PostPass", false);
|
||||
curr_effect->set_float("Brighten", 0.0f);
|
||||
|
||||
blit(NULL, false, poly->get_type(), vertnum, poly->get_count());
|
||||
}
|
||||
|
||||
|
||||
//============================================================
|
||||
// shaders::render_quad
|
||||
@ -1624,6 +1723,7 @@ void shaders::render_quad(poly_info *poly, int vertnum)
|
||||
}
|
||||
|
||||
curr_texture = poly->get_texture();
|
||||
curr_poly = poly;
|
||||
|
||||
if (PRIMFLAG_GET_SCREENTEX(d3d->get_last_texture_flags()) && curr_texture != NULL)
|
||||
{
|
||||
@ -1657,8 +1757,12 @@ void shaders::render_quad(poly_info *poly, int vertnum)
|
||||
next_index = post_pass(rt, next_index, poly, vertnum, false);
|
||||
next_index = bloom_pass(rt, next_index, poly, vertnum);
|
||||
|
||||
next_index = distortion_pass(rt, next_index, poly, vertnum);
|
||||
|
||||
// render on screen
|
||||
d3d->set_wrap(D3DTADDRESS_MIRROR);
|
||||
next_index = screen_pass(rt, next_index, poly, vertnum);
|
||||
d3d->set_wrap(PRIMFLAG_GET_TEXWRAP(poly->get_texture()->get_flags()) ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP);
|
||||
|
||||
curr_texture->increment_frame_count();
|
||||
curr_texture->mask_frame_count(options->yiq_phase_count);
|
||||
@ -1679,15 +1783,7 @@ void shaders::render_quad(poly_info *poly, int vertnum)
|
||||
|
||||
int next_index = 0;
|
||||
|
||||
float time_params[2] = { 0.0f, 0.0f };
|
||||
float length_params[3] = { poly->get_line_length(), options->vector_length_scale, options->vector_length_ratio };
|
||||
|
||||
curr_effect = vector_effect;
|
||||
curr_effect->update_uniforms();
|
||||
curr_effect->set_vector("TimeParams", 2, time_params);
|
||||
curr_effect->set_vector("LengthParams", 3, length_params);
|
||||
|
||||
blit(rt->prescale_target[next_index], true, poly->get_type(), vertnum, poly->get_count());
|
||||
next_index = vector_pass(rt, next_index, poly, vertnum);
|
||||
|
||||
HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, backbuffer);
|
||||
if (result != D3D_OK)
|
||||
@ -1704,21 +1800,13 @@ void shaders::render_quad(poly_info *poly, int vertnum)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
cache_target *ct = find_cache_target(rt->screen_index, rt->width, rt->height);
|
||||
|
||||
int next_index = 0;
|
||||
|
||||
curr_effect = default_effect;
|
||||
curr_effect->update_uniforms();
|
||||
|
||||
curr_effect->set_texture("Diffuse", rt->prescale_texture[next_index]);
|
||||
curr_effect->set_bool("PostPass", true);
|
||||
curr_effect->set_float("Brighten", 1.0f);
|
||||
|
||||
next_index = rt->next_index(next_index);
|
||||
blit(rt->prescale_target[next_index], true, poly->get_type(), vertnum, poly->get_count());
|
||||
|
||||
next_index = vector_buffer_pass(rt, next_index, poly, vertnum);
|
||||
next_index = defocus_pass(rt, next_index, poly, vertnum);
|
||||
next_index = phosphor_pass(rt, ct, next_index, poly, vertnum);
|
||||
|
||||
// create bloom textures
|
||||
@ -1731,6 +1819,8 @@ void shaders::render_quad(poly_info *poly, int vertnum)
|
||||
next_index = post_pass(rt, next_index, poly, vertnum, false);
|
||||
next_index = bloom_pass(rt, next_index, poly, vertnum);
|
||||
|
||||
next_index = distortion_pass(rt, next_index, poly, vertnum);
|
||||
|
||||
// render on screen
|
||||
next_index = screen_pass(rt, next_index, poly, vertnum);
|
||||
|
||||
@ -1744,16 +1834,12 @@ void shaders::render_quad(poly_info *poly, int vertnum)
|
||||
}
|
||||
else
|
||||
{
|
||||
curr_effect = default_effect;
|
||||
curr_effect->update_uniforms();
|
||||
curr_effect->set_bool("PostPass", false);
|
||||
curr_effect->set_float("Brighten", 0.0f);
|
||||
|
||||
blit(NULL, false, poly->get_type(), vertnum, poly->get_count());
|
||||
menu_pass(poly, vertnum);
|
||||
}
|
||||
|
||||
curr_render_target = NULL;
|
||||
curr_texture = NULL;
|
||||
curr_poly = NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -2040,6 +2126,11 @@ void shaders::delete_resources(bool reset)
|
||||
delete post_effect;
|
||||
post_effect = NULL;
|
||||
}
|
||||
if (distortion_effect != NULL)
|
||||
{
|
||||
delete distortion_effect;
|
||||
distortion_effect = NULL;
|
||||
}
|
||||
if (prescale_effect != NULL)
|
||||
{
|
||||
delete prescale_effect;
|
||||
@ -2151,9 +2242,9 @@ static void get_vector(const char *data, int count, float *out, int report_error
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
slider_alloc - allocate a new slider entry
|
||||
currently duplicated from ui.c, this could
|
||||
be done in a more ideal way.
|
||||
slider_alloc - allocate a new slider entry
|
||||
currently duplicated from ui.c, this could
|
||||
be done in a more ideal way.
|
||||
-------------------------------------------------*/
|
||||
|
||||
static slider_state *slider_alloc(running_machine &machine, const char *title, INT32 minval, INT32 defval, INT32 maxval, INT32 incval, slider_update update, void *arg)
|
||||
@ -2187,7 +2278,7 @@ static INT32 slider_set(float *option, float scale, const char *fmt, std::string
|
||||
{
|
||||
strprintf(*str, fmt, *option);
|
||||
}
|
||||
|
||||
|
||||
return floor(*option / scale + 0.5f);
|
||||
}
|
||||
|
||||
@ -2202,13 +2293,13 @@ static INT32 slider_shadow_mask_x_count(running_machine &machine, void *arg, std
|
||||
if (newval != SLIDER_NOCHANGE)
|
||||
{
|
||||
options->shadow_mask_count_x = newval;
|
||||
}
|
||||
}
|
||||
if (str != NULL)
|
||||
{
|
||||
strprintf(*str, "%d", options->shadow_mask_count_x);
|
||||
}
|
||||
options->params_dirty = true;
|
||||
|
||||
|
||||
return options->shadow_mask_count_x;
|
||||
}
|
||||
|
||||
@ -2224,7 +2315,7 @@ static INT32 slider_shadow_mask_y_count(running_machine &machine, void *arg, std
|
||||
strprintf(*str, "%d", options->shadow_mask_count_y);
|
||||
}
|
||||
options->params_dirty = true;
|
||||
|
||||
|
||||
return options->shadow_mask_count_y;
|
||||
}
|
||||
|
||||
@ -2643,77 +2734,77 @@ static INT32 slider_bloom_lvl10_scale(running_machine &machine, void *arg, std::
|
||||
|
||||
shaders::slider_desc shaders::s_sliders[] =
|
||||
{
|
||||
{ "Shadow Mask Darkness", 0, 0, 100, 1, slider_shadow_mask_alpha },
|
||||
{ "Shadow Mask X Count", 1, 6, 1024, 1, slider_shadow_mask_x_count },
|
||||
{ "Shadow Mask Y Count", 1, 6, 1024, 1, slider_shadow_mask_y_count },
|
||||
{ "Shadow Mask Pixel Count X", 1, 6, 64, 1, slider_shadow_mask_usize },
|
||||
{ "Shadow Mask Pixel Count Y", 1, 6, 64, 1, slider_shadow_mask_vsize },
|
||||
{ "Shadow Mask Offset X", -100, 0, 100, 1, slider_shadow_mask_uoffset },
|
||||
{ "Shadow Mask Offset Y", -100, 0, 100, 1, slider_shadow_mask_voffset },
|
||||
{ "Screen Curvature", 0, 3, 100, 1, slider_curvature },
|
||||
{ "Screen Round Corner", 0, 3, 100, 1, slider_round_corner },
|
||||
{ "Screen Reflection", 0, 3, 100, 1, slider_reflection },
|
||||
{ "Image Vignetting", 0, 3, 100, 1, slider_vignetting },
|
||||
{ "Scanline Darkness", 0, 100, 100, 1, slider_scanline_alpha },
|
||||
{ "Scanline Screen Height", 1, 20, 80, 1, slider_scanline_scale },
|
||||
{ "Scanline Indiv. Height", 1, 20, 80, 1, slider_scanline_height },
|
||||
{ "Scanline Brightness", 0, 20, 40, 1, slider_scanline_bright_scale },
|
||||
{ "Scanline Brightness Overdrive", 0, 0, 20, 1, slider_scanline_bright_offset },
|
||||
{ "Scanline Jitter", 0, 0, 40, 1, slider_scanline_offset },
|
||||
{ "Defocus X", 0, 0, 64, 1, slider_defocus_x },
|
||||
{ "Defocus Y", 0, 0, 64, 1, slider_defocus_y },
|
||||
{ "Red Position Offset X", -1500, 3, 1500, 1, slider_red_converge_x },
|
||||
{ "Red Position Offset Y", -1500, 0, 1500, 1, slider_red_converge_y },
|
||||
{ "Green Position Offset X", -1500, 0, 1500, 1, slider_green_converge_x },
|
||||
{ "Green Position Offset Y", -1500, 3, 1500, 1, slider_green_converge_y },
|
||||
{ "Blue Position Offset X", -1500, 3, 1500, 1, slider_blue_converge_x },
|
||||
{ "Blue Position Offset Y", -1500, 3, 1500, 1, slider_blue_converge_y },
|
||||
{ "Red Convergence X", -1500, 0, 1500, 1, slider_red_radial_converge_x },
|
||||
{ "Red Convergence Y", -1500, 0, 1500, 1, slider_red_radial_converge_y },
|
||||
{ "Green Convergence X", -1500, 0, 1500, 1, slider_green_radial_converge_x },
|
||||
{ "Green Convergence Y", -1500, 0, 1500, 1, slider_green_radial_converge_y },
|
||||
{ "Blue Convergence X", -1500, 0, 1500, 1, slider_blue_radial_converge_x },
|
||||
{ "Blue Convergence Y", -1500, 0, 1500, 1, slider_blue_radial_converge_y },
|
||||
{ "Red Output from Red Input", -400, 0, 400, 5, slider_red_from_r },
|
||||
{ "Red Output from Green Input", -400, 0, 400, 5, slider_red_from_g },
|
||||
{ "Red Output from Blue Input", -400, 0, 400, 5, slider_red_from_b },
|
||||
{ "Green Output from Red Input", -400, 0, 400, 5, slider_green_from_r },
|
||||
{ "Green Output from Green Input", -400, 0, 400, 5, slider_green_from_g },
|
||||
{ "Green Output from Blue Input", -400, 0, 400, 5, slider_green_from_b },
|
||||
{ "Blue Output from Red Input", -400, 0, 400, 5, slider_blue_from_r },
|
||||
{ "Blue Output from Green Input", -400, 0, 400, 5, slider_blue_from_g },
|
||||
{ "Blue Output from Blue Input", -400, 0, 400, 5, slider_blue_from_b },
|
||||
{ "Saturation", 0, 140, 400, 1, slider_saturation },
|
||||
{ "Red DC Offset", -100, 0, 100, 1, slider_red_offset },
|
||||
{ "Green DC Offset", -100, 0, 100, 1, slider_green_offset },
|
||||
{ "Blue DC Offset", -100, 0, 100, 1, slider_blue_offset },
|
||||
{ "Red Scale", -200, 95, 200, 1, slider_red_scale },
|
||||
{ "Green Scale", -200, 95, 200, 1, slider_green_scale },
|
||||
{ "Blue Scale", -200, 95, 200, 1, slider_blue_scale },
|
||||
{ "Red Gamma", -80, 16, 80, 1, slider_red_power },
|
||||
{ "Green Gamma", -80, 16, 80, 1, slider_green_power },
|
||||
{ "Blue Gamma", -80, 16, 80, 1, slider_blue_power },
|
||||
{ "Red Floor", 0, 5, 100, 1, slider_red_floor },
|
||||
{ "Green Floor", 0, 5, 100, 1, slider_green_floor },
|
||||
{ "Blue Floor", 0, 5, 100, 1, slider_blue_floor },
|
||||
{ "Red Phosphor Life", 0, 40, 100, 1, slider_red_phosphor_life },
|
||||
{ "Green Phosphor Life", 0, 40, 100, 1, slider_green_phosphor_life },
|
||||
{ "Blue Phosphor Life", 0, 40, 100, 1, slider_blue_phosphor_life },
|
||||
{ "Vector Length Attenuation", 0, 80, 100, 1, slider_vector_attenuation },
|
||||
{ "Vector Attenuation Length Limit", 1, 500, 1000, 1, slider_vector_length_max },
|
||||
{ "Vector Bloom Scale", 0, 300, 1000, 5, slider_vector_bloom_scale },
|
||||
{ "Raster Bloom Scale", 0, 225, 1000, 5, slider_raster_bloom_scale },
|
||||
{ "Bloom Level 0 Scale", 0, 100, 100, 1, slider_bloom_lvl0_scale },
|
||||
{ "Bloom Level 1 Scale", 0, 21, 100, 1, slider_bloom_lvl1_scale },
|
||||
{ "Bloom Level 2 Scale", 0, 19, 100, 1, slider_bloom_lvl2_scale },
|
||||
{ "Bloom Level 3 Scale", 0, 17, 100, 1, slider_bloom_lvl3_scale },
|
||||
{ "Bloom Level 4 Scale", 0, 15, 100, 1, slider_bloom_lvl4_scale },
|
||||
{ "Bloom Level 5 Scale", 0, 14, 100, 1, slider_bloom_lvl5_scale },
|
||||
{ "Bloom Level 6 Scale", 0, 13, 100, 1, slider_bloom_lvl6_scale },
|
||||
{ "Bloom Level 7 Scale", 0, 12, 100, 1, slider_bloom_lvl7_scale },
|
||||
{ "Bloom Level 8 Scale", 0, 11, 100, 1, slider_bloom_lvl8_scale },
|
||||
{ "Bloom Level 9 Scale", 0, 10, 100, 1, slider_bloom_lvl9_scale },
|
||||
{ "Bloom Level 10 Scale", 0, 9, 100, 1, slider_bloom_lvl10_scale },
|
||||
{ "Shadow Mask Darkness", 0, 0, 100, 1, slider_shadow_mask_alpha },
|
||||
{ "Shadow Mask X Count", 1, 6, 1024, 1, slider_shadow_mask_x_count },
|
||||
{ "Shadow Mask Y Count", 1, 6, 1024, 1, slider_shadow_mask_y_count },
|
||||
{ "Shadow Mask Pixel Count X", 1, 6, 64, 1, slider_shadow_mask_usize },
|
||||
{ "Shadow Mask Pixel Count Y", 1, 6, 64, 1, slider_shadow_mask_vsize },
|
||||
{ "Shadow Mask Offset X", -100, 0, 100, 1, slider_shadow_mask_uoffset },
|
||||
{ "Shadow Mask Offset Y", -100, 0, 100, 1, slider_shadow_mask_voffset },
|
||||
{ "Screen Curvature", 0, 3, 100, 1, slider_curvature },
|
||||
{ "Screen Round Corner", 0, 3, 100, 1, slider_round_corner },
|
||||
{ "Screen Reflection", 0, 3, 100, 1, slider_reflection },
|
||||
{ "Image Vignetting", 0, 3, 100, 1, slider_vignetting },
|
||||
{ "Scanline Darkness", 0, 100, 100, 1, slider_scanline_alpha },
|
||||
{ "Scanline Screen Height", 1, 20, 80, 1, slider_scanline_scale },
|
||||
{ "Scanline Indiv. Height", 1, 20, 80, 1, slider_scanline_height },
|
||||
{ "Scanline Brightness", 0, 20, 40, 1, slider_scanline_bright_scale },
|
||||
{ "Scanline Brightness Overdrive", 0, 0, 20, 1, slider_scanline_bright_offset },
|
||||
{ "Scanline Jitter", 0, 0, 40, 1, slider_scanline_offset },
|
||||
{ "Defocus X", 0, 0, 64, 1, slider_defocus_x },
|
||||
{ "Defocus Y", 0, 0, 64, 1, slider_defocus_y },
|
||||
{ "Red Position Offset X", -1500, 3, 1500, 1, slider_red_converge_x },
|
||||
{ "Red Position Offset Y", -1500, 0, 1500, 1, slider_red_converge_y },
|
||||
{ "Green Position Offset X", -1500, 0, 1500, 1, slider_green_converge_x },
|
||||
{ "Green Position Offset Y", -1500, 3, 1500, 1, slider_green_converge_y },
|
||||
{ "Blue Position Offset X", -1500, 3, 1500, 1, slider_blue_converge_x },
|
||||
{ "Blue Position Offset Y", -1500, 3, 1500, 1, slider_blue_converge_y },
|
||||
{ "Red Convergence X", -1500, 0, 1500, 1, slider_red_radial_converge_x },
|
||||
{ "Red Convergence Y", -1500, 0, 1500, 1, slider_red_radial_converge_y },
|
||||
{ "Green Convergence X", -1500, 0, 1500, 1, slider_green_radial_converge_x },
|
||||
{ "Green Convergence Y", -1500, 0, 1500, 1, slider_green_radial_converge_y },
|
||||
{ "Blue Convergence X", -1500, 0, 1500, 1, slider_blue_radial_converge_x },
|
||||
{ "Blue Convergence Y", -1500, 0, 1500, 1, slider_blue_radial_converge_y },
|
||||
{ "Red Output from Red Input", -400, 0, 400, 5, slider_red_from_r },
|
||||
{ "Red Output from Green Input", -400, 0, 400, 5, slider_red_from_g },
|
||||
{ "Red Output from Blue Input", -400, 0, 400, 5, slider_red_from_b },
|
||||
{ "Green Output from Red Input", -400, 0, 400, 5, slider_green_from_r },
|
||||
{ "Green Output from Green Input", -400, 0, 400, 5, slider_green_from_g },
|
||||
{ "Green Output from Blue Input", -400, 0, 400, 5, slider_green_from_b },
|
||||
{ "Blue Output from Red Input", -400, 0, 400, 5, slider_blue_from_r },
|
||||
{ "Blue Output from Green Input", -400, 0, 400, 5, slider_blue_from_g },
|
||||
{ "Blue Output from Blue Input", -400, 0, 400, 5, slider_blue_from_b },
|
||||
{ "Saturation", 0, 140, 400, 1, slider_saturation },
|
||||
{ "Red DC Offset", -100, 0, 100, 1, slider_red_offset },
|
||||
{ "Green DC Offset", -100, 0, 100, 1, slider_green_offset },
|
||||
{ "Blue DC Offset", -100, 0, 100, 1, slider_blue_offset },
|
||||
{ "Red Scale", -200, 95, 200, 1, slider_red_scale },
|
||||
{ "Green Scale", -200, 95, 200, 1, slider_green_scale },
|
||||
{ "Blue Scale", -200, 95, 200, 1, slider_blue_scale },
|
||||
{ "Red Gamma", -80, 16, 80, 1, slider_red_power },
|
||||
{ "Green Gamma", -80, 16, 80, 1, slider_green_power },
|
||||
{ "Blue Gamma", -80, 16, 80, 1, slider_blue_power },
|
||||
{ "Red Floor", 0, 5, 100, 1, slider_red_floor },
|
||||
{ "Green Floor", 0, 5, 100, 1, slider_green_floor },
|
||||
{ "Blue Floor", 0, 5, 100, 1, slider_blue_floor },
|
||||
{ "Red Phosphor Life", 0, 40, 100, 1, slider_red_phosphor_life },
|
||||
{ "Green Phosphor Life", 0, 40, 100, 1, slider_green_phosphor_life },
|
||||
{ "Blue Phosphor Life", 0, 40, 100, 1, slider_blue_phosphor_life },
|
||||
{ "Vector Length Attenuation", 0, 80, 100, 1, slider_vector_attenuation },
|
||||
{ "Vector Attenuation Length Limit", 1, 500, 1000, 1, slider_vector_length_max },
|
||||
{ "Vector Bloom Scale", 0, 300, 1000, 5, slider_vector_bloom_scale },
|
||||
{ "Raster Bloom Scale", 0, 225, 1000, 5, slider_raster_bloom_scale },
|
||||
{ "Bloom Level 0 Scale", 0, 100, 100, 1, slider_bloom_lvl0_scale },
|
||||
{ "Bloom Level 1 Scale", 0, 21, 100, 1, slider_bloom_lvl1_scale },
|
||||
{ "Bloom Level 2 Scale", 0, 19, 100, 1, slider_bloom_lvl2_scale },
|
||||
{ "Bloom Level 3 Scale", 0, 17, 100, 1, slider_bloom_lvl3_scale },
|
||||
{ "Bloom Level 4 Scale", 0, 15, 100, 1, slider_bloom_lvl4_scale },
|
||||
{ "Bloom Level 5 Scale", 0, 14, 100, 1, slider_bloom_lvl5_scale },
|
||||
{ "Bloom Level 6 Scale", 0, 13, 100, 1, slider_bloom_lvl6_scale },
|
||||
{ "Bloom Level 7 Scale", 0, 12, 100, 1, slider_bloom_lvl7_scale },
|
||||
{ "Bloom Level 8 Scale", 0, 11, 100, 1, slider_bloom_lvl8_scale },
|
||||
{ "Bloom Level 9 Scale", 0, 10, 100, 1, slider_bloom_lvl9_scale },
|
||||
{ "Bloom Level 10 Scale", 0, 9, 100, 1, slider_bloom_lvl10_scale },
|
||||
{ NULL, 0, 0, 0, 0, NULL },
|
||||
};
|
||||
|
||||
@ -2816,8 +2907,22 @@ void uniform::update()
|
||||
}
|
||||
case CU_TARGET_DIMS:
|
||||
{
|
||||
float rtsize[2] = { shadersys->curr_render_target->target_width, shadersys->curr_render_target->target_height };
|
||||
m_shader->set_vector("TargetDims", 2, rtsize);
|
||||
if (shadersys->curr_render_target == NULL)
|
||||
{
|
||||
float targetdims[2] = { 0.0f, 0.0f };
|
||||
m_shader->set_vector("TargetDims", 2, targetdims);
|
||||
}
|
||||
else
|
||||
{
|
||||
float targetdims[2] = { shadersys->curr_render_target->target_width, shadersys->curr_render_target->target_height };
|
||||
m_shader->set_vector("TargetDims", 2, targetdims);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CU_QUAD_DIMS:
|
||||
{
|
||||
float quaddims[2] = { shadersys->curr_poly->get_prim_width(), shadersys->curr_poly->get_prim_height() };
|
||||
m_shader->set_vector("QuadDims", 2, quaddims);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,7 @@ public:
|
||||
CU_SOURCE_DIMS,
|
||||
CU_SOURCE_RECT,
|
||||
CU_TARGET_DIMS,
|
||||
CU_QUAD_DIMS,
|
||||
|
||||
CU_NTSC_CCFREQ,
|
||||
CU_NTSC_A,
|
||||
@ -337,7 +338,11 @@ private:
|
||||
int post_pass(render_target *rt, int source_index, poly_info *poly, int vertnum, bool prepare_bloom);
|
||||
int downsample_pass(render_target *rt, int source_index, poly_info *poly, int vertnum);
|
||||
int bloom_pass(render_target *rt, int source_index, poly_info *poly, int vertnum);
|
||||
int distortion_pass(render_target *rt, int source_index, poly_info *poly, int vertnum);
|
||||
int vector_pass(render_target *rt, int source_index, poly_info *poly, int vertnum);
|
||||
int vector_buffer_pass(render_target *rt, int source_index, poly_info *poly, int vertnum);
|
||||
int screen_pass(render_target *rt, int source_index, poly_info *poly, int vertnum);
|
||||
void menu_pass(poly_info *poly, int vertnum);
|
||||
|
||||
base * d3dintf; // D3D interface
|
||||
|
||||
@ -400,6 +405,7 @@ private:
|
||||
effect * default_effect; // pointer to the primary-effect object
|
||||
effect * prescale_effect; // pointer to the prescale-effect object
|
||||
effect * post_effect; // pointer to the post-effect object
|
||||
effect * distortion_effect; // pointer to the distortion-effect object
|
||||
effect * focus_effect; // pointer to the focus-effect object
|
||||
effect * phosphor_effect; // pointer to the phosphor-effect object
|
||||
effect * deconverge_effect; // pointer to the deconvergence-effect object
|
||||
@ -413,6 +419,7 @@ private:
|
||||
|
||||
texture_info * curr_texture;
|
||||
render_target * curr_render_target;
|
||||
poly_info * curr_poly;
|
||||
|
||||
public:
|
||||
render_target * targethead;
|
||||
|
@ -2757,26 +2757,30 @@ cache_target::~cache_target()
|
||||
|
||||
bool cache_target::init(renderer *d3d, base *d3dintf, int width, int height, int prescale_x, int prescale_y)
|
||||
{
|
||||
int bloom_size = (width < height) ? width : height;
|
||||
int bloom_index = 0;
|
||||
int bloom_size = (width < height) ? width : height;
|
||||
int bloom_width = width;
|
||||
int bloom_height = height;
|
||||
for (; bloom_size >= 2 && bloom_index < 11; bloom_size >>= 1)
|
||||
{
|
||||
bloom_width >>= 1;
|
||||
bloom_height >>= 1;
|
||||
|
||||
HRESULT result = (*d3dintf->device.create_texture)(d3d->get_device(), bloom_width, bloom_height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &bloom_texture[bloom_index]);
|
||||
if (result != D3D_OK)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
(*d3dintf->texture.get_surface_level)(bloom_texture[bloom_index], 0, &bloom_target[bloom_index]);
|
||||
|
||||
bloom_index++;
|
||||
}
|
||||
|
||||
HRESULT result = (*d3dintf->device.create_texture)(d3d->get_device(), width * prescale_x, height * prescale_y, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &last_texture);
|
||||
if (result != D3D_OK)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
(*d3dintf->texture.get_surface_level)(last_texture, 0, &last_target);
|
||||
|
||||
target_width = width * prescale_x;
|
||||
@ -2804,8 +2808,8 @@ render_target::~render_target()
|
||||
(*d3dintf->surface.release)(bloom_target[index]);
|
||||
bloom_target[index] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (int index = 0; index < 2; index++)
|
||||
{
|
||||
if (native_texture[index] != NULL)
|
||||
@ -2837,34 +2841,42 @@ render_target::~render_target()
|
||||
//============================================================
|
||||
|
||||
bool render_target::init(renderer *d3d, base *d3dintf, int width, int height, int prescale_x, int prescale_y)
|
||||
{
|
||||
{
|
||||
HRESULT result;
|
||||
|
||||
|
||||
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]);
|
||||
if (result != D3D_OK)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
(*d3dintf->texture.get_surface_level)(native_texture[index], 0, &native_target[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]);
|
||||
if (result != D3D_OK)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
(*d3dintf->texture.get_surface_level)(prescale_texture[index], 0, &prescale_target[index]);
|
||||
}
|
||||
|
||||
float bloom_size = (d3d->get_width() < d3d->get_height()) ? d3d->get_width() : d3d->get_height();
|
||||
int bloom_index = 0;
|
||||
float bloom_size = (d3d->get_width() < d3d->get_height()) ? d3d->get_width() : d3d->get_height();
|
||||
float bloom_width = d3d->get_width();
|
||||
float bloom_height = d3d->get_height();
|
||||
for (; bloom_size >= 2.0f && bloom_index < 11; bloom_size *= 0.5f)
|
||||
{
|
||||
bloom_width *= 0.5f;
|
||||
bloom_height *= 0.5f;
|
||||
|
||||
result = (*d3dintf->device.create_texture)(d3d->get_device(), (int)bloom_width, (int)bloom_height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &bloom_texture[bloom_index]);
|
||||
if (result != D3D_OK)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
(*d3dintf->texture.get_surface_level)(bloom_texture[bloom_index], 0, &bloom_target[bloom_index]);
|
||||
|
||||
bloom_index++;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user