Bloom refactoring

- calculation of bloom dimensions is now done only once, when render
target is created
- reduced blur width for non-vector screens
- implemented shadow u/v option for source tile mode
This commit is contained in:
ImJezze 2016-02-25 20:58:49 +01:00
parent d44f8f4c2b
commit 11395616dd
7 changed files with 83 additions and 77 deletions

View File

@ -202,8 +202,9 @@ float random(float2 seed)
uniform float2 ScreenDims; uniform float2 ScreenDims;
uniform float2 TargetDims; uniform float2 TargetDims;
uniform float2 SourceRect; uniform float2 SourceDims;
// level dimensions not necessary anymore?
uniform float2 Level0Size; uniform float2 Level0Size;
uniform float4 Level12Size; uniform float4 Level12Size;
uniform float4 Level34Size; uniform float4 Level34Size;
@ -211,6 +212,8 @@ uniform float4 Level56Size;
uniform float4 Level78Size; uniform float4 Level78Size;
uniform float4 Level9ASize; uniform float4 Level9ASize;
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;
@ -226,12 +229,17 @@ 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)
Output.TexCoord0 = TexCoord; Output.TexCoord0 = TexCoord.xy; // + (0.5f / Level0Size);
Output.TexCoord12 = TexCoord.xyxy + (0.5f / Level12Size);
Output.TexCoord34 = TexCoord.xyxy + (0.5f / Level34Size); TexCoord += VectorScreen
Output.TexCoord56 = TexCoord.xyxy + (0.5f / Level56Size); ? 0.5f / TargetDims.xy
Output.TexCoord78 = TexCoord.xyxy + (0.5f / Level78Size); : 0.5f / SourceDims.xy;
Output.TexCoord9A = TexCoord.xyxy + (0.5f / Level9ASize);
Output.TexCoord12 = TexCoord.xyxy; // + (0.5f / Level12Size);
Output.TexCoord34 = TexCoord.xyxy; // + (0.5f / Level34Size);
Output.TexCoord56 = TexCoord.xyxy; // + (0.5f / Level56Size);
Output.TexCoord78 = TexCoord.xyxy; // + (0.5f / Level78Size);
Output.TexCoord9A = TexCoord.xyxy; // + (0.5f / Level9ASize);
return Output; return Output;
} }

View File

@ -57,6 +57,8 @@ uniform float2 SourceDims;
uniform float2 SourceRect; uniform float2 SourceRect;
uniform float2 QuadDims; uniform float2 QuadDims;
uniform int BloomLevel;
uniform bool VectorScreen; uniform bool VectorScreen;
static const float2 Coord0Offset = float2(-0.5f, -0.5f); static const float2 Coord0Offset = float2(-0.5f, -0.5f);
@ -68,9 +70,7 @@ 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 HalfTargetTexelDims = 0.5f / 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;
@ -83,17 +83,10 @@ 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; Output.TexCoord01.xy = TexCoord + Coord0Offset * HalfTargetTexelDims;
float2 RasterTexelOffset = SourceTexelDims * (0.5f * SourceRect) * (1.0f - (QuadDims / ScreenDims)); Output.TexCoord01.zw = TexCoord + Coord1Offset * HalfTargetTexelDims;
Output.TexCoord23.xy = TexCoord + Coord2Offset * HalfTargetTexelDims;
TexCoord += VectorScreen Output.TexCoord23.zw = TexCoord + Coord3Offset * HalfTargetTexelDims;
? VectorTexelOffset
: RasterTexelOffset;
Output.TexCoord01.xy = TexCoord + Coord0Offset * TargetTexelDims;
Output.TexCoord01.zw = TexCoord + Coord1Offset * TargetTexelDims;
Output.TexCoord23.xy = TexCoord + Coord2Offset * TargetTexelDims;
Output.TexCoord23.zw = TexCoord + Coord3Offset * TargetTexelDims;
return Output; return Output;
} }

View File

@ -97,17 +97,14 @@ VS_OUTPUT vs_main(VS_INPUT Input)
Output.Position.xy *= 2.0f; // zoom Output.Position.xy *= 2.0f; // zoom
Output.TexCoord = Input.Position.xy / ScreenDims; Output.TexCoord = Input.Position.xy / ScreenDims;
Output.TexCoord += 0.5f / TargetDims; // half texel offset correction (DX9)
Output.TexCoord += PrepareBloom
? 0.0f / TargetDims // use half texel offset (DX9) to do the blur for first bloom layer
: 0.5f / TargetDims; // fix half texel offset correction (DX9)
Output.SourceCoord = Input.TexCoord; Output.SourceCoord = Input.TexCoord;
float2 ScreenCoordOffset = ShadowUVOffset;
ScreenCoordOffset = SwapXY
? ShadowUVOffset.yx
: ShadowUVOffset.xy;
Output.ScreenCoord = Input.Position.xy / ScreenDims; Output.ScreenCoord = Input.Position.xy / ScreenDims;
Output.ScreenCoord += ScreenCoordOffset / ScreenDims;
Output.Color = Input.Color; Output.Color = Input.Color;
@ -173,22 +170,31 @@ float4 ps_main(PS_INPUT Input) : COLOR
float4 BaseColor = tex2D(DiffuseSampler, TexCoord); float4 BaseColor = tex2D(DiffuseSampler, TexCoord);
BaseColor.a = 1.0f; BaseColor.a = 1.0f;
clip(TexCoord < 0.0f || TexCoord > 1.0f ? -1 : 1); // keep border
if (!PrepareBloom)
{
// clip border
clip(TexCoord < 0.0f || TexCoord > 1.0f ? -1 : 1);
}
// Mask Simulation (may not affect bloom) // Mask Simulation (may not affect bloom)
if (!PrepareBloom && ShadowAlpha > 0.0f) if (!PrepareBloom && ShadowAlpha > 0.0f)
{ {
float2 shadowUVOffset = ShadowUVOffset;
shadowUVOffset = SwapXY
? ShadowUVOffset.yx
: ShadowUVOffset.xy;
float2 shadowDims = ShadowDims; float2 shadowDims = ShadowDims;
shadowDims = SwapXY shadowDims = SwapXY
? shadowDims.yx ? shadowDims.yx
: shadowDims.xy; : shadowDims.xy;
float2 shadowUV = ShadowUV; float2 shadowUV = ShadowUV;
// shadowUV = SwapXY
// ? shadowUV.yx
// : shadowUV.xy;
float2 screenCoord = ShadowTileMode == 0 ? ScreenCoord : SourceCoord; float2 screenCoord = ShadowTileMode == 0
? ScreenCoord + shadowUVOffset / ScreenDims
: SourceCoord + shadowUVOffset / SourceDims;
screenCoord = SwapXY screenCoord = SwapXY
? screenCoord.yx ? screenCoord.yx
: screenCoord.xy; : screenCoord.xy;
@ -198,17 +204,17 @@ 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 * shadowCount
: SourceTexelDims * shadowCount;
shadowTile = SwapXY shadowTile = SwapXY
? shadowTile.yx ? shadowTile.yx
: shadowTile.xy; : shadowTile.xy;
float2 ShadowFrac = frac(screenCoord / shadowTile); float2 ShadowFrac = frac(screenCoord / shadowTile);
float2 ShadowCoord = (ShadowFrac * shadowUV); float2 ShadowCoord = (ShadowFrac * shadowUV);
ShadowCoord += 0.5f / shadowDims; // half texel offset ShadowCoord += 0.5f / shadowDims; // half texel offset
// ShadowCoord = SwapXY
// ? ShadowCoord.yx
// : ShadowCoord.xy;
float4 ShadowColor = tex2D(ShadowSampler, ShadowCoord); float4 ShadowColor = tex2D(ShadowSampler, ShadowCoord);
float3 ShadowMaskColor = lerp(1.0f, ShadowColor.rgb, ShadowAlpha); float3 ShadowMaskColor = lerp(1.0f, ShadowColor.rgb, ShadowAlpha);

View File

@ -292,8 +292,12 @@ public:
d3d_render_target *next; d3d_render_target *next;
d3d_render_target *prev; d3d_render_target *prev;
surface *bloom_target[11]; surface *bloom_surface[11];
texture *bloom_texture[11]; texture *bloom_texture[11];
float bloom_dims[11][2];
int bloom_count;
}; };
#endif #endif

View File

@ -60,7 +60,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), bloom_count(0), d3dintf(NULL), machine(NULL), d3d(NULL), num_screens(0), curr_screen(0), curr_frame(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),
@ -1444,32 +1444,19 @@ int shaders::downsample_pass(d3d_render_target *rt, int source_index, poly_info
curr_effect = downsample_effect; curr_effect = downsample_effect;
curr_effect->update_uniforms(); curr_effect->update_uniforms();
int bloom_index = 0; for (int bloom_index = 0; bloom_index < rt->bloom_count; bloom_index++)
float bloom_width = rt->target_width;
float bloom_height = rt->target_height;
float bloom_size = bloom_width < bloom_height ? bloom_width : bloom_height;
for (; bloom_size >= 2.0f && bloom_index < 11; bloom_size *= 0.5f)
{ {
bloom_dims[bloom_index][0] = (float)(int)bloom_width; curr_effect->set_vector("TargetDims", 2, rt->bloom_dims[bloom_index]);
bloom_dims[bloom_index][1] = (float)(int)bloom_height; curr_effect->set_int("BloomLevel", bloom_index + 1);
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->source_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_surface[bloom_index], true, D3DPT_TRIANGLELIST, 0, 2);
blit(rt->bloom_target[bloom_index], true, poly->get_type(), vertnum, poly->get_count()); blit(rt->bloom_surface[bloom_index], true, poly->get_type(), vertnum, poly->get_count());
bloom_width *= 0.5f;
bloom_height *= 0.5f;
bloom_index++;
} }
bloom_count = bloom_index;
return next_index; return next_index;
} }
@ -1514,12 +1501,12 @@ int shaders::bloom_pass(d3d_render_target *rt, int source_index, poly_info *poly
curr_effect->set_vector("Level78Weight", 2, weight78); curr_effect->set_vector("Level78Weight", 2, weight78);
curr_effect->set_vector("Level9AWeight", 2, weight9A); curr_effect->set_vector("Level9AWeight", 2, weight9A);
curr_effect->set_vector("Level0Size", 2, bloom_dims[0]); curr_effect->set_vector("Level0Size", 2, rt->bloom_dims[0]);
curr_effect->set_vector("Level12Size", 4, bloom_dims[1]); curr_effect->set_vector("Level12Size", 4, rt->bloom_dims[1]);
curr_effect->set_vector("Level34Size", 4, bloom_dims[3]); curr_effect->set_vector("Level34Size", 4, rt->bloom_dims[3]);
curr_effect->set_vector("Level56Size", 4, bloom_dims[5]); curr_effect->set_vector("Level56Size", 4, rt->bloom_dims[5]);
curr_effect->set_vector("Level78Size", 4, bloom_dims[7]); curr_effect->set_vector("Level78Size", 4, rt->bloom_dims[7]);
curr_effect->set_vector("Level9ASize", 4, bloom_dims[9]); curr_effect->set_vector("Level9ASize", 4, rt->bloom_dims[9]);
curr_effect->set_int("BloomBlendMode", options->bloom_blend_mode); curr_effect->set_int("BloomBlendMode", options->bloom_blend_mode);
curr_effect->set_float("BloomScale", options->bloom_scale); curr_effect->set_float("BloomScale", options->bloom_scale);
@ -1528,12 +1515,12 @@ int shaders::bloom_pass(d3d_render_target *rt, int source_index, poly_info *poly
curr_effect->set_texture("DiffuseA", rt->target_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 < rt->bloom_count; index++)
{ {
name[7] = 'A' + index; name[7] = 'A' + index;
curr_effect->set_texture(name, rt->bloom_texture[index - 1]); curr_effect->set_texture(name, rt->bloom_texture[index - 1]);
} }
for (int index = bloom_count; index < 11; index++) for (int index = rt->bloom_count; index < 11; index++)
{ {
name[7] = 'A' + index; name[7] = 'A' + index;
curr_effect->set_texture(name, black_texture); curr_effect->set_texture(name, black_texture);

View File

@ -380,8 +380,6 @@ 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
float bloom_dims[11][2]; // bloom texture dimensions
int bloom_count; // count of used bloom textures
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

@ -2770,10 +2770,10 @@ d3d_render_target::~d3d_render_target()
(*d3dintf->texture.release)(bloom_texture[index]); (*d3dintf->texture.release)(bloom_texture[index]);
bloom_texture[index] = nullptr; bloom_texture[index] = nullptr;
} }
if (bloom_target[index] != nullptr) if (bloom_surface[index] != nullptr)
{ {
(*d3dintf->surface.release)(bloom_target[index]); (*d3dintf->surface.release)(bloom_surface[index]);
bloom_target[index] = nullptr; bloom_surface[index] = nullptr;
} }
} }
@ -2836,23 +2836,33 @@ bool d3d_render_target::init(renderer_d3d9 *d3d, d3d_base *d3dintf, int width, i
(*d3dintf->texture.get_surface_level)(target_texture[index], 0, &target_surface[index]); (*d3dintf->texture.get_surface_level)(target_texture[index], 0, &target_surface[index]);
} }
int bloom_index = 0; bool vector_screen =
float bloom_width = target_width; d3d->window().machine().first_screen()->screen_type() == SCREEN_TYPE_VECTOR;
float bloom_height = target_height;
// larger blur width for vector screens than raster screens
float scale_factor = vector_screen ? 0.5f : 0.75f;
float bloom_width = (float)width;
float bloom_height = (float)height;
float bloom_size = bloom_width < bloom_height ? bloom_width : bloom_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 (int bloom_index = 0; bloom_index < 11 && bloom_size >= 2.0f; bloom_size *= scale_factor)
{ {
bloom_width *= 0.5f; this->bloom_dims[bloom_index][0] = (int)bloom_width;
bloom_height *= 0.5f; this->bloom_dims[bloom_index][1] = (int)bloom_height;
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]); 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) if (result != D3D_OK)
{ {
return false; return false;
} }
(*d3dintf->texture.get_surface_level)(bloom_texture[bloom_index], 0, &bloom_target[bloom_index]); (*d3dintf->texture.get_surface_level)(bloom_texture[bloom_index], 0, &bloom_surface[bloom_index]);
bloom_width *= scale_factor;
bloom_height *= scale_factor;
bloom_index++; bloom_index++;
this->bloom_count = bloom_index;
} }
return true; return true;