Fixed several small issues in HLSL/BGFX

* fixed target texture dimension when -intoverscan is used (this fixes the appereance of scanline and shadow mask)
* added target_scale and screen_count uniforms
* rounded corners now remain aligned with screen bounds when -intoverscan is used (single screen only)
master
Jezze 2016-09-28 15:22:38 +02:00
parent 4727ff5e6a
commit ecf1e166fc
28 changed files with 265 additions and 125 deletions

View File

@ -28,7 +28,9 @@
{ "name": "s_tex", "type": "int", "values": [ 0.0 ] },
{ "name": "u_swap_xy", "type": "vec4", "values": [ 0.0, 0.0, 0.0, 0.0 ] },
{ "name": "u_screen_dims", "type": "vec4", "values": [ 1.0, 1.0, 0.0, 0.0 ] },
{ "name": "u_screen_count", "type": "vec4", "values": [ 1.0, 0.0, 0.0, 0.0 ] },
{ "name": "u_target_dims", "type": "vec4", "values": [ 1.0, 1.0, 0.0, 0.0 ] },
{ "name": "u_target_scale", "type": "vec4", "values": [ 1.0, 1.0, 0.0, 0.0 ] },
{ "name": "u_quad_dims", "type": "vec4", "values": [ 1.0, 1.0, 0.0, 0.0 ] },
{ "name": "u_distortion", "type": "vec4", "values": [ 0.20, 0.0, 0.0, 0.0 ] },
{ "name": "u_cubic_distortion", "type": "vec4", "values": [ 0.20, 0.0, 0.0, 0.0 ] },

View File

@ -29,6 +29,8 @@
{ "name": "s_shadow", "type": "int", "values": [ 1.0 ] },
{ "name": "u_swap_xy", "type": "vec4", "values": [ 0.0, 0.0, 0.0, 0.0 ] },
{ "name": "u_source_dims", "type": "vec4", "values": [ 256.0, 256.0, 0.0, 0.0 ] },
{ "name": "u_target_dims", "type": "vec4", "values": [ 256.0, 256.0, 0.0, 0.0 ] },
{ "name": "u_target_scale", "type": "vec4", "values": [ 1.0, 1.0, 0.0, 0.0 ] },
{ "name": "u_quad_dims", "type": "vec4", "values": [ 256.0, 256.0, 0.0, 0.0 ] },
{ "name": "u_humbar_hertz_rate", "type": "vec4", "values": [ 0.001, 0.0, 0.0, 0.0 ] },
{ "name": "u_humbar_alpha", "type": "vec4", "values": [ 0.0, 0.0, 0.0, 0.0 ] },

View File

@ -86,7 +86,9 @@ float roundBox(float2 p, float2 b, float r)
//-----------------------------------------------------------------------------
uniform float2 ScreenDims; // size of the window or fullscreen
uniform int ScreenCount;
uniform float2 TargetDims; // size of the target surface
uniform float2 TargetScale;
uniform float2 QuadDims; // size of the screen quad
VS_OUTPUT vs_main(VS_INPUT Input)
@ -170,7 +172,7 @@ float GetSpotAddend(float2 coord, float amount)
return saturate(SigmoidSpot);
}
float GetRoundCornerFactor(float2 coord, float2 bounds, float radiusAmount, float smoothAmount)
float GetBoundsFactor(float2 coord, float2 bounds, float radiusAmount, float smoothAmount)
{
// reduce smooth amount down to radius amount
smoothAmount = min(smoothAmount, radiusAmount);
@ -216,7 +218,7 @@ float2 GetDistortedCoords(float2 centerCoord, float amount, float amountCube)
return centerCoord;
}
float2 GetCoords(float2 coord, float distortionAmount, float cubicDistortionAmount)
float2 GetTextureCoords(float2 coord, float distortionAmount, float cubicDistortionAmount)
{
// center coordinates
coord -= 0.5f;
@ -230,35 +232,61 @@ float2 GetCoords(float2 coord, float distortionAmount, float cubicDistortionAmou
return coord;
}
float2 GetQuadCoords(float2 coord, float distortionAmount, float cubicDistortionAmount)
{
// center coordinates
coord -= 0.5f;
// keep coords inside of the quad bounds of a single screen
if (ScreenCount == 1)
{
// base-target dimensions (without oversampling)
float2 BaseTargetDims = TargetDims / TargetScale;
// apply base-target/quad difference
coord *= BaseTargetDims / (SwapXY ? QuadDims.yx : QuadDims.xy);
}
// distort coordinates
coord = GetDistortedCoords(coord, distortionAmount, cubicDistortionAmount);
return coord;
}
float4 ps_main(PS_INPUT Input) : COLOR
{
// image distortion
float distortionAmount = DistortionAmount;
float cubicDistortionAmount = CubicDistortionAmount > 0.0f
? CubicDistortionAmount * 1.1f // cubic distortion need to be a little higher to compensate the quartic distortion
: CubicDistortionAmount * 1.2f; // negativ values even more
// corner distortion at least by the amount of the image distorition
float distortCornerAmount = max(DistortCornerAmount, DistortionAmount + CubicDistortionAmount);
float roundCornerAmount = RoundCornerAmount * 0.5f;
float smoothBorderAmount = SmoothBorderAmount * 0.5f;
float2 TexelDims = 1.0f / TargetDims;
// Screen Curvature
float2 TexCoord = GetCoords(Input.TexCoord, distortionAmount, cubicDistortionAmount);
// base-target dimensions (without oversampling)
float2 BaseTargetDims = TargetDims / TargetScale;
// Corner Curvature
float2 CornerCoord = GetCoords(Input.TexCoord, DistortCornerAmount, 0.0f);
// Screen Texture Curvature
float2 BaseCoord = GetTextureCoords(Input.TexCoord, distortionAmount, cubicDistortionAmount);
// Screen Quad Curvature
float2 QuadCoord = GetQuadCoords(Input.TexCoord, distortCornerAmount, 0.0f);
// clip border
clip(TexCoord < 0.0f - TexelDims || TexCoord > 1.0f + TexelDims ? -1 : 1);
float2 TexCoordCentered = TexCoord;
TexCoordCentered -= 0.5f;
float2 CornerCoordCentered = CornerCoord;
CornerCoordCentered -= 0.5f;
clip(BaseCoord < 0.0f - TexelDims || BaseCoord > 1.0f + TexelDims ? -1 : 1);
// Color
float4 BaseColor = tex2D(DiffuseSampler, TexCoord);
float4 BaseColor = tex2D(DiffuseSampler, BaseCoord);
BaseColor.a = 1.0f;
// Vignetting Simulation
float2 VignetteCoord = CornerCoordCentered;
float2 VignetteCoord = QuadCoord;
float VignetteFactor = GetVignetteFactor(VignetteCoord, VignettingAmount);
BaseColor.rgb *= VignetteFactor;
@ -266,20 +294,23 @@ float4 ps_main(PS_INPUT Input) : COLOR
// Light Reflection Simulation
float3 LightColor = float3(1.0f, 0.90f, 0.80f); // color temperature 5.000 Kelvin
float2 SpotCoord = CornerCoordCentered;
float2 NoiseCoord = CornerCoordCentered;
float2 SpotCoord = QuadCoord;
float2 NoiseCoord = QuadCoord;
float SpotAddend = GetSpotAddend(SpotCoord, ReflectionAmount);
float NoiseFactor = GetNoiseFactor(SpotAddend, random(NoiseCoord));
BaseColor.rgb += SpotAddend * NoiseFactor * LightColor;
// Round Corners Simulation
float2 RoundCornerCoord = CornerCoordCentered;
float2 RoundCornerBounds = SwapXY
? QuadDims.yx
: QuadDims.xy;
float2 RoundCornerCoord = QuadCoord;
float2 RoundCornerBounds = ScreenCount == 1
? QuadDims // align corners to quad bounds of a single screen
: BaseTargetDims; // align corners to target bounds of multiple screens
RoundCornerBounds = SwapXY
? RoundCornerBounds.yx
: RoundCornerBounds.xy;
float roundCornerFactor = GetRoundCornerFactor(RoundCornerCoord, RoundCornerBounds, RoundCornerAmount * 0.5f, SmoothBorderAmount * 0.5f);
float roundCornerFactor = GetBoundsFactor(RoundCornerCoord, RoundCornerBounds, roundCornerAmount, smoothBorderAmount);
BaseColor.rgb *= roundCornerFactor;
return BaseColor;

View File

@ -76,6 +76,7 @@ static const float HalfPI = PI * 0.5f;
uniform float2 ScreenDims;
uniform float2 SourceDims;
uniform float2 TargetDims;
uniform float2 TargetScale;
uniform float2 QuadDims;
uniform float2 ShadowDims = float2(32.0f, 32.0f); // size of the shadow texture (extended to power-of-two size)
@ -158,17 +159,20 @@ float2 GetAdjustedCoords(float2 coord)
return coord;
}
float2 GetShadowCoord(float2 QuadCoord, float2 SourceCoord)
float2 GetShadowCoord(float2 TargetCoord, float2 SourceCoord)
{
float2 QuadTexel = 1.0f / QuadDims;
float2 SourceTexel = 1.0f / SourceDims;
// base-target dimensions (without oversampling)
float2 BaseTargetDims = TargetDims / TargetScale;
BaseTargetDims = SwapXY
? BaseTargetDims.yx
: BaseTargetDims.xy;
float2 canvasCoord = ShadowTileMode == 0
? QuadCoord + ShadowUVOffset / QuadDims
? TargetCoord + ShadowUVOffset / BaseTargetDims
: SourceCoord + ShadowUVOffset / SourceDims;
float2 canvasTexelDims = ShadowTileMode == 0
? QuadTexel
: SourceTexel;
? 1.0f / BaseTargetDims
: 1.0f / SourceDims;
float2 shadowDims = ShadowDims;
float2 shadowUV = ShadowUV;
@ -204,15 +208,15 @@ float2 GetShadowCoord(float2 QuadCoord, float2 SourceCoord)
float4 ps_main(PS_INPUT Input) : COLOR
{
float2 ScreenCoord = Input.ScreenCoord;
float2 TexCoord = GetAdjustedCoords(Input.TexCoord);
float2 BaseCoord = GetAdjustedCoords(Input.TexCoord);
float2 SourceCoord = GetAdjustedCoords(Input.SourceCoord);
// Color
float4 BaseColor = tex2D(DiffuseSampler, TexCoord);
float4 BaseColor = tex2D(DiffuseSampler, BaseCoord);
BaseColor.a = 1.0f;
// clip border
clip(TexCoord < 0.0f || TexCoord > 1.0f ? -1 : 1);
clip(BaseCoord < 0.0f || BaseCoord > 1.0f ? -1 : 1);
// Mask Simulation (may not affect bloom)
if (!PrepareBloom && ShadowAlpha > 0.0f)

View File

@ -40,7 +40,6 @@ struct VS_INPUT
float4 Position : POSITION;
float4 Color : COLOR0;
float2 TexCoord : TEXCOORD0;
float2 Unused : TEXCOORD1;
};
struct PS_INPUT

View File

@ -53,7 +53,6 @@ static const float Epsilon = 1.0e-7f;
uniform float2 ScreenDims;
uniform float2 TargetDims;
uniform float2 QuadDims;
VS_OUTPUT vs_screen_main(VS_INPUT Input)
{

View File

@ -46,7 +46,7 @@ float roundBox(float2 p, float2 b, float r)
//-----------------------------------------------------------------------------
uniform float2 ScreenDims;
uniform float2 QuadDims;
uniform float2 TargetDims;
VS_OUTPUT vs_main(VS_INPUT Input)
{
@ -76,7 +76,7 @@ uniform float LengthRatio; // Size at which fade is maximum
uniform float LengthScale; // How much length affects the vector's fade
uniform float BeamSmooth;
float GetRoundCornerFactor(float2 coord, float2 bounds, float radiusAmount, float smoothAmount)
float GetBoundsFactor(float2 coord, float2 bounds, float radiusAmount, float smoothAmount)
{
// reduce smooth amount down to radius amount
smoothAmount = min(smoothAmount, radiusAmount);
@ -100,7 +100,7 @@ float GetRoundCornerFactor(float2 coord, float2 bounds, float radiusAmount, floa
float4 ps_main(PS_INPUT Input) : COLOR
{
float2 lineSize = Input.SizeInfo / max(QuadDims.x, QuadDims.y); // normalize
float2 lineSize = Input.SizeInfo / max(TargetDims.x, TargetDims.y); // normalize
float lineLength = lineSize.x;
float lineLengthRatio = LengthRatio;
@ -113,7 +113,7 @@ float4 ps_main(PS_INPUT Input) : COLOR
float4 outColor = float4(timeLengthModulate, timeLengthModulate, timeLengthModulate, 1.0f);
outColor *= Input.Color;
float RoundCornerFactor = GetRoundCornerFactor(Input.TexCoord - 0.5f, Input.SizeInfo, 1.0f, BeamSmooth);
float RoundCornerFactor = GetBoundsFactor(Input.TexCoord - 0.5f, Input.SizeInfo, 1.0f, BeamSmooth);
outColor.rgb *= RoundCornerFactor;
return outColor;

View File

@ -1402,6 +1402,7 @@ render_primitive_list &render_target::get_primitives()
{
render_primitive *prim = list.alloc(render_primitive::QUAD);
set_render_bounds_xy(&prim->bounds, 0.0f, 0.0f, (float)m_width, (float)m_height);
prim->full_bounds = prim->bounds;
set_render_color(&prim->color, 1.0f, 1.0f, 1.0f, 1.0f);
prim->texture.base = nullptr;
prim->flags = PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA);
@ -1411,6 +1412,7 @@ render_primitive_list &render_target::get_primitives()
{
prim = list.alloc(render_primitive::QUAD);
set_render_bounds_xy(&prim->bounds, 1.0f, 1.0f, (float)(m_width - 1), (float)(m_height - 1));
prim->full_bounds = prim->bounds;
set_render_color(&prim->color, 1.0f, 0.0f, 0.0f, 0.0f);
prim->texture.base = nullptr;
prim->flags = PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA);
@ -1855,6 +1857,9 @@ void render_target::add_container_primitives(render_primitive_list &list, const
prim->color.b = container_xform.color.b * curitem.color().b;
prim->color.a = container_xform.color.a * curitem.color().a;
// copy unclipped bounds
prim->full_bounds = prim->bounds;
// now switch off the type
bool clipped = true;
switch (curitem.type())
@ -1917,7 +1922,7 @@ void render_target::add_container_primitives(render_primitive_list &list, const
clipped = render_clip_quad(&prim->bounds, &cliprect, &prim->texcoords);
// apply the final orientation from the quad flags and then build up the final flags
prim->flags = (curitem.flags() & ~(PRIMFLAG_TEXORIENT_MASK | PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK))
prim->flags |= (curitem.flags() & ~(PRIMFLAG_TEXORIENT_MASK | PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK))
| PRIMFLAG_TEXORIENT(finalorient)
| PRIMFLAG_TEXFORMAT(curitem.texture()->format());
prim->flags |= blendmode != -1
@ -1977,7 +1982,7 @@ void render_target::add_container_primitives(render_primitive_list &list, const
clipped = render_clip_quad(&prim->bounds, &cliprect, &prim->texcoords);
// apply the final orientation from the quad flags and then build up the final flags
prim->flags = (curitem.flags() & ~(PRIMFLAG_TEXORIENT_MASK | PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK))
prim->flags |= (curitem.flags() & ~(PRIMFLAG_TEXORIENT_MASK | PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK))
| PRIMFLAG_TEXORIENT(finalorient);
prim->flags |= blendmode != -1
? PRIMFLAG_BLENDMODE(blendmode)
@ -1986,7 +1991,7 @@ void render_target::add_container_primitives(render_primitive_list &list, const
else
{
// set the basic flags
prim->flags = (curitem.flags() & ~PRIMFLAG_BLENDMODE_MASK)
prim->flags |= (curitem.flags() & ~PRIMFLAG_BLENDMODE_MASK)
| PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA);
// apply clipping
@ -2008,22 +2013,23 @@ void render_target::add_container_primitives(render_primitive_list &list, const
// allocate a primitive
render_primitive *prim = list.alloc(render_primitive::QUAD);
set_render_bounds_wh(&prim->bounds, xform.xoffs, xform.yoffs, xform.xscale, xform.yscale);
prim->full_bounds = prim->bounds;
prim->color = container_xform.color;
width = render_round_nearest(prim->bounds.x1) - render_round_nearest(prim->bounds.x0);
height = render_round_nearest(prim->bounds.y1) - render_round_nearest(prim->bounds.y0);
container.overlay()->get_scaled(
(container_xform.orientation & ORIENTATION_SWAP_XY) ? height : width,
(container_xform.orientation & ORIENTATION_SWAP_XY) ? width : height, prim->texture, list);
(container_xform.orientation & ORIENTATION_SWAP_XY) ? height : width,
(container_xform.orientation & ORIENTATION_SWAP_XY) ? width : height, prim->texture, list);
// determine UV coordinates
prim->texcoords = oriented_texcoords[container_xform.orientation];
// set the flags and add it to the list
prim->flags = PRIMFLAG_TEXORIENT(container_xform.orientation) |
PRIMFLAG_BLENDMODE(BLENDMODE_RGB_MULTIPLY) |
PRIMFLAG_TEXFORMAT(container.overlay()->format()) |
PRIMFLAG_TEXSHADE(1);
prim->flags = PRIMFLAG_TEXORIENT(container_xform.orientation)
| PRIMFLAG_BLENDMODE(BLENDMODE_RGB_MULTIPLY)
| PRIMFLAG_TEXFORMAT(container.overlay()->format())
| PRIMFLAG_TEXSHADE(1);
list.append_or_return(*prim, false);
}
@ -2057,6 +2063,7 @@ void render_target::add_element_primitives(render_primitive_list &list, const ob
INT32 width = render_round_nearest(xform.xscale);
INT32 height = render_round_nearest(xform.yscale);
set_render_bounds_wh(&prim->bounds, render_round_nearest(xform.xoffs), render_round_nearest(xform.yoffs), (float) width, (float) height);
prim->full_bounds = prim->bounds;
if (xform.orientation & ORIENTATION_SWAP_XY)
std::swap(width, height);
width = std::min(width, m_maxtexwidth);
@ -2511,6 +2518,7 @@ void render_target::add_clear_extents(render_primitive_list &list)
{
render_primitive *prim = list.alloc(render_primitive::QUAD);
set_render_bounds_xy(&prim->bounds, (float)x0, (float)y0, (float)x1, (float)y1);
prim->full_bounds = prim->bounds;
set_render_color(&prim->color, 1.0f, 0.0f, 0.0f, 0.0f);
prim->texture.base = nullptr;
prim->flags = PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA);

View File

@ -203,7 +203,7 @@ struct render_color
// render_texuv - floating point set of UV texture coordinates
struct render_texuv
{
float u; // U coodinate (0.0-1.0)
float u; // U coordinate (0.0-1.0)
float v; // V coordinate (0.0-1.0)
};
@ -345,8 +345,10 @@ public:
// getters
render_primitive *next() const { return m_next; }
bool packable(const INT32 pack_size) const { return (flags & PRIMFLAG_PACKABLE) && texture.base != nullptr && texture.width <= pack_size && texture.height <= pack_size; }
float get_quad_width() const { return bounds.x1 - bounds.x0; }
float get_quad_height() const { return bounds.y1 - bounds.y0; }
float get_quad_width() const { return abs(bounds.x1 - bounds.x0); }
float get_quad_height() const { return abs(bounds.y1 - bounds.y0); }
float get_full_quad_width() const { return abs(full_bounds.x1 - full_bounds.x0); }
float get_full_quad_height() const { return abs(full_bounds.y1 - full_bounds.y0); }
// reset to prepare for re-use
void reset();
@ -354,6 +356,7 @@ public:
// public state
primitive_type type; // type of primitive
render_bounds bounds; // bounds or positions
render_bounds full_bounds; // bounds or positions (unclipped)
render_color color; // RGBA values
UINT32 flags; // flags
float width; // width (for line primitives)
@ -602,8 +605,8 @@ private:
user_settings m_user; // user settings
bitmap_argb32 * m_overlaybitmap; // overlay bitmap
render_texture * m_overlaytexture; // overlay texture
std::unique_ptr<palette_client> m_palclient; // client to the screen palette
std::vector<rgb_t> m_bcglookup; // copy of screen palette with bcg adjustment
std::unique_ptr<palette_client> m_palclient; // client to the screen palette
std::vector<rgb_t> m_bcglookup; // copy of screen palette with bcg adjustment
rgb_t m_bcglookup256[0x400]; // lookup table for brightness/contrast/gamma
};

View File

@ -77,9 +77,9 @@ void bgfx_chain::process(render_primitive* prim, int view, int screen, texture_m
screen_device_iterator screen_iterator(window.machine().root_device());
screen_device* screen_device = screen_iterator.byindex(screen);
int current_view = view;
uint16_t screen_width(floor((prim->bounds.x1 - prim->bounds.x0) + 0.5f));
uint16_t screen_height(floor((prim->bounds.y1 - prim->bounds.y0) + 0.5f));
uint16_t screen_count(window.target()->current_view()->screens().count());
uint16_t screen_width(floor(prim->get_quad_width() + 0.5f));
uint16_t screen_height(floor(prim->get_quad_height() + 0.5f));
uint32_t rotation_type =
(window.target()->orientation() & ROT90) == ROT90 ? 1 :
(window.target()->orientation() & ROT180) == ROT180 ? 2 :
@ -101,11 +101,12 @@ void bgfx_chain::process(render_primitive* prim, int view, int screen, texture_m
screen_offset_y = -screen_container.yoffset();
}
int current_view = view;
for (bgfx_chain_entry* entry : m_entries)
{
if (!entry->skip())
{
entry->submit(current_view, prim, textures, screen_width, screen_height, screen_scale_x, screen_scale_y, screen_offset_x, screen_offset_y, rotation_type, swap_xy, blend, screen);
entry->submit(current_view, prim, textures, screen_count, screen_width, screen_height, screen_scale_x, screen_scale_y, screen_offset_x, screen_offset_y, rotation_type, swap_xy, blend, screen);
current_view++;
}
}

View File

@ -55,7 +55,7 @@ bgfx_chain_entry::~bgfx_chain_entry()
delete m_clear;
}
void bgfx_chain_entry::submit(int view, render_primitive* prim, texture_manager& textures, uint16_t screen_width, uint16_t screen_height, float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, uint32_t rotation_type, bool swap_xy, uint64_t blend, int32_t screen)
void bgfx_chain_entry::submit(int view, render_primitive* prim, texture_manager& textures, uint16_t screen_count, uint16_t screen_width, uint16_t screen_height, float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, uint32_t rotation_type, bool swap_xy, uint64_t blend, int32_t screen)
{
bgfx::setViewSeq(view, true);
@ -73,7 +73,7 @@ void bgfx_chain_entry::submit(int view, render_primitive* prim, texture_manager&
put_screen_buffer(prim, &buffer);
bgfx::setVertexBuffer(&buffer);
setup_auto_uniforms(prim, textures, screen_width, screen_height, screen_scale_x, screen_scale_y, screen_offset_x, screen_offset_y, rotation_type, swap_xy, screen);
setup_auto_uniforms(prim, textures, screen_count, screen_width, screen_height, screen_scale_x, screen_scale_y, screen_offset_x, screen_offset_y, rotation_type, swap_xy, screen);
for (bgfx_entry_uniform* uniform : m_uniforms)
{
@ -137,6 +137,16 @@ void bgfx_chain_entry::setup_screenoffset_uniforms(float screen_offset_x, float
}
}
void bgfx_chain_entry::setup_screencount_uniforms(uint16_t screen_count)
{
bgfx_uniform* u_screen_count = m_effect->uniform("u_screen_count");
if (u_screen_count != nullptr)
{
float values[1] = { float(screen_count) };
u_screen_count->set(values, sizeof(float));
}
}
void bgfx_chain_entry::setup_sourcesize_uniform(render_primitive* prim) const
{
bgfx_uniform* source_dims = m_effect->uniform("u_source_dims");
@ -161,6 +171,20 @@ void bgfx_chain_entry::setup_targetsize_uniform(int32_t screen) const
}
}
void bgfx_chain_entry::setup_targetscale_uniform(int32_t screen) const
{
bgfx_uniform* target_scale = m_effect->uniform("u_target_scale");
if (target_scale != nullptr)
{
bgfx_target* output = m_targets.target(screen, m_output);
if (output != nullptr)
{
float values[2] = { float(output->scale()), float(output->scale()) };
target_scale->set(values, sizeof(float) * 2);
}
}
}
void bgfx_chain_entry::setup_rotationtype_uniform(uint32_t rotation_type) const
{
bgfx_uniform* rotation_type_uniform = m_effect->uniform("u_rotation_type");
@ -201,13 +225,15 @@ void bgfx_chain_entry::setup_screenindex_uniform(int32_t screen) const
}
}
void bgfx_chain_entry::setup_auto_uniforms(render_primitive* prim, texture_manager& textures, uint16_t screen_width, uint16_t screen_height, float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, uint32_t rotation_type, bool swap_xy, int32_t screen)
void bgfx_chain_entry::setup_auto_uniforms(render_primitive* prim, texture_manager& textures, uint16_t screen_count, uint16_t screen_width, uint16_t screen_height, float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, uint32_t rotation_type, bool swap_xy, int32_t screen)
{
setup_screensize_uniforms(textures, screen_width, screen_height, screen);
setup_screenscale_uniforms(screen_scale_x, screen_scale_y);
setup_screenoffset_uniforms(screen_offset_x, screen_offset_y);
setup_screencount_uniforms(screen_count);
setup_sourcesize_uniform(prim);
setup_targetsize_uniform(screen);
setup_targetscale_uniform(screen);
setup_rotationtype_uniform(rotation_type);
setup_swapxy_uniform(swap_xy);
setup_quaddims_uniform(prim);

View File

@ -37,7 +37,7 @@ public:
bgfx_chain_entry(std::string name, bgfx_effect* effect, clear_state* clear, std::vector<bgfx_suppressor*> suppressors, std::vector<bgfx_input_pair*> inputs, std::vector<bgfx_entry_uniform*> uniforms, target_manager& targets, std::string output);
~bgfx_chain_entry();
void submit(int view, render_primitive* prim, texture_manager& textures, uint16_t screen_width, uint16_t screen_height, float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, uint32_t rotation_type, bool swap_xy, uint64_t blend, int32_t screen);
void submit(int view, render_primitive* prim, texture_manager& textures, uint16_t screen_count, uint16_t screen_width, uint16_t screen_height, float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, uint32_t rotation_type, bool swap_xy, uint64_t blend, int32_t screen);
// Getters
std::string name() const { return m_name; }
@ -45,12 +45,14 @@ public:
bool skip();
private:
void setup_auto_uniforms(render_primitive* prim, texture_manager& textures, uint16_t screen_width, uint16_t screen_height, float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, uint32_t rotation_type, bool swap_xy, int32_t screen);
void setup_auto_uniforms(render_primitive* prim, texture_manager& textures, uint16_t screen_count, uint16_t screen_width, uint16_t screen_height, float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, uint32_t rotation_type, bool swap_xy, int32_t screen);
void setup_screensize_uniforms(texture_manager& textures, uint16_t screen_width, uint16_t screen_height, int32_t screen);
void setup_screenscale_uniforms(float screen_scale_x, float screen_scale_y);
void setup_screenoffset_uniforms(float screen_offset_x, float screen_offset_y);
void setup_screencount_uniforms(uint16_t screen_count);
void setup_sourcesize_uniform(render_primitive* prim) const;
void setup_targetsize_uniform(int32_t screen) const;
void setup_targetscale_uniform(int32_t screen) const;
void setup_rotationtype_uniform(uint32_t rotation_type) const;
void setup_swapxy_uniform(bool swap_xy) const;
void setup_quaddims_uniform(render_primitive* prim) const;

View File

@ -435,8 +435,8 @@ uint32_t chain_manager::handle_screen_chains(uint32_t view, render_primitive *st
continue;
}
uint16_t screen_width(floor((prim->bounds.x1 - prim->bounds.x0) + 0.5f));
uint16_t screen_height(floor((prim->bounds.y1 - prim->bounds.y0) + 0.5f));
uint16_t screen_width(floor(prim->get_full_quad_width() + 0.5f));
uint16_t screen_height(floor(prim->get_full_quad_height() + 0.5f));
if (window.swap_xy())
{
std::swap(screen_width, screen_height);

View File

@ -11,7 +11,9 @@ $input v_color0, v_texcoord0
// Autos
uniform vec4 u_swap_xy;
uniform vec4 u_screen_dims;
uniform vec4 u_screen_count;
uniform vec4 u_target_dims;
uniform vec4 u_target_scale;
uniform vec4 u_quad_dims;
// User-supplied
@ -97,7 +99,7 @@ float GetSpotAddend(vec2 coord, float amount)
return saturate(SigmoidSpot);
}
float GetRoundCornerFactor(vec2 coord, vec2 bounds, float radiusAmount, float smoothAmount)
float GetBoundsFactor(vec2 coord, vec2 bounds, float radiusAmount, float smoothAmount)
{
// reduce smooth amount down to radius amount
smoothAmount = min(smoothAmount, radiusAmount);
@ -141,7 +143,7 @@ vec2 GetDistortedCoords(vec2 centerCoord, float amount, float amountCube)
return centerCoord;
}
vec2 GetCoords(vec2 coord, float distortionAmount, float cubicDistortionAmount)
vec2 GetTextureCoords(vec2 coord, float distortionAmount, float cubicDistortionAmount)
{
// center coordinates
coord -= 0.5;
@ -155,6 +157,27 @@ vec2 GetCoords(vec2 coord, float distortionAmount, float cubicDistortionAmount)
return coord;
}
vec2 GetQuadCoords(vec2 coord, float distortionAmount, float cubicDistortionAmount)
{
// center coordinates
coord -= 0.5;
// keep coords inside of the quad bounds of a single screen
if (u_screen_count.x > 0.0 && u_screen_count.x < 2.0)
{
// base-target dimensions (without oversampling)
vec2 BaseTargetDims = u_target_dims.xy / u_target_scale.xy;
// apply base-target/quad difference
coord *= BaseTargetDims / ((u_swap_xy.x > 0.0) ? u_quad_dims.yx : u_quad_dims.xy);
}
// distort coordinates
coord = GetDistortedCoords(coord, distortionAmount, cubicDistortionAmount);
return coord;
}
// Shader
void main()
@ -164,18 +187,22 @@ void main()
? u_cubic_distortion.x * 1.1 // cubic distortion need to be a little higher to compensate the quartic distortion
: u_cubic_distortion.x * 1.2; // negativ values even more
// corner distortion at least by the amount of the image distorition
float distortCornerAmount = max(u_distort_corner.x, u_distortion.x + u_cubic_distortion.x);
float roundCornerAmount = u_round_corner.x * 0.5;
float smoothBorderAmount = u_smooth_border.x * 0.5;
vec2 TexelDims = vec2(1.0 / u_target_dims.x, 1.0 / u_target_dims.y);
// Screen Curvature
vec2 BaseCoord = GetCoords(v_texcoord0, distortionAmount, cubicDistortionAmount);
// base-target dimensions (without oversampling)
vec2 BaseTargetDims = u_target_dims.xy / u_target_scale.xy;
// Corner Curvature
vec2 CornerCoord = GetCoords(v_texcoord0, u_distort_corner.x, 0.0);
// Screen Texture Curvature
vec2 BaseCoord = GetTextureCoords(v_texcoord0, distortionAmount, cubicDistortionAmount);
vec2 BaseCoordCentered = BaseCoord;
BaseCoordCentered -= 0.5;
vec2 CornerCoordCentered = CornerCoord;
CornerCoordCentered -= 0.5;
// Screen Quad Curvature
vec2 QuadCoord = GetQuadCoords(v_texcoord0, distortCornerAmount, 0.0);
// Color
vec4 BaseColor = texture2D(s_tex, BaseCoord);
@ -188,7 +215,7 @@ void main()
else
{
// Vignetting Simulation
vec2 VignetteCoord = CornerCoordCentered;
vec2 VignetteCoord = QuadCoord;
float VignetteFactor = GetVignetteFactor(VignetteCoord, u_vignetting.x);
BaseColor.rgb *= VignetteFactor;
@ -196,20 +223,23 @@ void main()
// Light Reflection Simulation
vec4 LightColor = vec4(1.0, 0.90, 0.80, 1.0); // color temperature 5.000 Kelvin
vec2 SpotCoord = CornerCoordCentered;
vec2 NoiseCoord = CornerCoordCentered;
vec2 SpotCoord = QuadCoord;
vec2 NoiseCoord = QuadCoord;
float SpotAddend = GetSpotAddend(SpotCoord, u_reflection.x);
float NoiseFactor = GetNoiseFactor(SpotAddend, rand(NoiseCoord));
BaseColor += SpotAddend * NoiseFactor * LightColor;
// Round Corners Simulation
vec2 RoundCornerCoord = CornerCoordCentered;
vec2 RoundCornerBounds = (u_swap_xy.x > 0.0)
? u_quad_dims.yx
: u_quad_dims.xy;
vec2 RoundCornerCoord = QuadCoord;
vec2 RoundCornerBounds = (u_screen_count.x > 0.0 && u_screen_count.x < 2.0)
? u_quad_dims.xy // align corners to screen quad bounds
: BaseTargetDims; // align corners to target texture bounds
RoundCornerBounds = (u_swap_xy.x > 0.0)
? RoundCornerBounds.yx
: RoundCornerBounds.xy;
float roundCornerFactor = GetRoundCornerFactor(RoundCornerCoord, RoundCornerBounds, u_round_corner.x * 0.5f, u_smooth_border.x * 0.5f);
float roundCornerFactor = GetBoundsFactor(RoundCornerCoord, RoundCornerBounds, roundCornerAmount, smoothBorderAmount);
BaseColor.rgb *= roundCornerFactor;
gl_FragColor = BaseColor;

View File

@ -11,6 +11,8 @@ $input v_color0, v_texcoord0
// Autos
uniform vec4 u_swap_xy;
uniform vec4 u_source_dims; // size of the guest machine
uniform vec4 u_target_dims;
uniform vec4 u_target_scale;
uniform vec4 u_quad_dims;
uniform vec4 u_screen_scale;
uniform vec4 u_screen_offset;
@ -63,13 +65,19 @@ vec2 GetAdjustedCoords(vec2 coord)
return coord;
}
vec2 GetShadowCoord(vec2 QuadCoord, vec2 SourceCoord)
vec2 GetShadowCoord(vec2 TargetCoord, vec2 SourceCoord)
{
// base-target dimensions (remove oversampling)
vec2 BaseTargetDims = u_target_dims.xy / u_target_scale.xy;
BaseTargetDims = u_swap_xy.x > 0.0
? BaseTargetDims.yx
: BaseTargetDims.xy;
vec2 canvasCoord = u_shadow_tile_mode.x == 0.0
? QuadCoord + u_shadow_uv_offset.xy / u_quad_dims.xy
? TargetCoord + u_shadow_uv_offset.xy / BaseTargetDims
: SourceCoord + u_shadow_uv_offset.xy / u_source_dims.xy;
vec2 canvasTexelDims = u_shadow_tile_mode.x == 0.0
? vec2(1.0, 1.0) / u_quad_dims.xy
? vec2(1.0, 1.0) / BaseTargetDims
: vec2(1.0, 1.0) / u_source_dims.xy;
vec2 shadowUV = u_shadow_uv.xy;

View File

@ -787,7 +787,9 @@ int shaders::create_resources()
{
effects[i]->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS);
effects[i]->add_uniform("TargetDims", uniform::UT_VEC2, uniform::CU_TARGET_DIMS);
effects[i]->add_uniform("TargetScale", uniform::UT_FLOAT, uniform::CU_TARGET_SCALE);
effects[i]->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS);
effects[i]->add_uniform("ScreenCount", uniform::UT_INT, uniform::CU_SCREEN_COUNT);
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("VectorScreen", uniform::UT_BOOL, uniform::CU_VECTOR_SCREEN);
@ -1018,9 +1020,9 @@ rgb_t shaders::apply_color_convolution(rgb_t color)
{
// this function uses the same algorithm as the color convolution shader pass
float r = static_cast<float>(color.r()) / 255.0f;
float g = static_cast<float>(color.g()) / 255.0f;
float b = static_cast<float>(color.b()) / 255.0f;
float r = float(color.r()) / 255.0f;
float g = float(color.g()) / 255.0f;
float b = float(color.b()) / 255.0f;
float *rRatio = options->red_ratio;
float *gRatio = options->grn_ratio;
@ -1049,9 +1051,9 @@ rgb_t shaders::apply_color_convolution(rgb_t color)
b = chroma[2] * saturation + luma;
return rgb_t(
std::max(0, std::min(255, static_cast<int>(r * 255.0f))),
std::max(0, std::min(255, static_cast<int>(g * 255.0f))),
std::max(0, std::min(255, static_cast<int>(b * 255.0f))));
std::max(0, std::min(255, int(r * 255.0f))),
std::max(0, std::min(255, int(g * 255.0f))),
std::max(0, std::min(255, int(b * 255.0f))));
}
int shaders::color_convolution_pass(d3d_render_target *rt, int source_index, poly_info *poly, int vertnum)
@ -1161,6 +1163,8 @@ int shaders::post_pass(d3d_render_target *rt, int source_index, poly_info *poly,
{
int next_index = source_index;
auto win = d3d->assert_window();
screen_device_iterator screen_iterator(machine->root_device());
screen_device *screen = screen_iterator.byindex(curr_screen);
render_container &screen_container = screen->container();
@ -1177,9 +1181,9 @@ int shaders::post_pass(d3d_render_target *rt, int source_index, poly_info *poly,
: rgb_t(0, 0, 0);
back_color_rgb = apply_color_convolution(back_color_rgb);
float back_color[3] = {
static_cast<float>(back_color_rgb.r()) / 255.0f,
static_cast<float>(back_color_rgb.g()) / 255.0f,
static_cast<float>(back_color_rgb.b()) / 255.0f };
float(back_color_rgb.r()) / 255.0f,
float(back_color_rgb.g()) / 255.0f,
float(back_color_rgb.b()) / 255.0f };
curr_effect = post_effect;
curr_effect->update_uniforms();
@ -1582,8 +1586,8 @@ d3d_render_target* shaders::get_texture_target(render_primitive *prim, texture_i
auto win = d3d->assert_window();
int target_width = int(prim->get_quad_width() + 0.5f);
int target_height = int(prim->get_quad_height() + 0.5f);
int target_width = int(prim->get_full_quad_width() + 0.5f);
int target_height = int(prim->get_full_quad_height() + 0.5f);
target_width *= oversampling_enable ? 2 : 1;
target_height *= oversampling_enable ? 2 : 1;
if (win->swap_xy())
@ -1618,11 +1622,10 @@ d3d_render_target* shaders::get_vector_target(render_primitive *prim)
auto win = d3d->assert_window();
// source and target size are the same for vector targets
int source_width = int(prim->get_quad_width() + 0.5f);
int source_height = int(prim->get_quad_height() + 0.5f);
int target_width = source_width;
int target_height = source_height;
int target_width = int(prim->get_full_quad_width() + 0.5f);
int target_height = int(prim->get_full_quad_height() + 0.5f);
target_width *= oversampling_enable ? 2 : 1;
target_height *= oversampling_enable ? 2 : 1;
if (win->swap_xy())
@ -1658,11 +1661,10 @@ bool shaders::create_vector_target(render_primitive *prim)
auto win = d3d->assert_window();
// source and target size are the same for vector targets
int source_width = int(prim->get_quad_width() + 0.5f);
int source_height = int(prim->get_quad_height() + 0.5f);
int target_width = source_width;
int target_height = source_height;
int target_width = int(prim->get_full_quad_width() + 0.5f);
int target_height = int(prim->get_full_quad_height() + 0.5f);
target_width *= oversampling_enable ? 2 : 1;
target_height *= oversampling_enable ? 2 : 1;
if (win->swap_xy())
@ -1748,8 +1750,8 @@ bool shaders::register_texture(render_primitive *prim, texture_info *texture)
int source_width = texture->get_width();
int source_height = texture->get_height();
int target_width = int(prim->get_quad_width() + 0.5f);
int target_height = int(prim->get_quad_height() + 0.5f);
int target_width = int(prim->get_full_quad_width() + 0.5f);
int target_height = int(prim->get_full_quad_height() + 0.5f);
target_width *= oversampling_enable ? 2 : 1;
target_height *= oversampling_enable ? 2 : 1;
if (win->swap_xy())
@ -2339,6 +2341,12 @@ void uniform::update()
m_shader->set_vector("ScreenDims", 2, &screendims.c.x);
break;
}
case CU_SCREEN_COUNT:
{
int screen_count = win->target()->current_view()->screens().count();
m_shader->set_int("ScreenCount", screen_count);
break;
}
case CU_SOURCE_DIMS:
{
if (vector_screen)
@ -2347,8 +2355,8 @@ void uniform::update()
{
// vector screen has no source texture, so take the source dimensions of the render target
float sourcedims[2] = {
static_cast<float>(shadersys->curr_render_target->width),
static_cast<float>(shadersys->curr_render_target->height) };
float(shadersys->curr_render_target->width),
float(shadersys->curr_render_target->height) };
m_shader->set_vector("SourceDims", 2, sourcedims);
}
}
@ -2367,20 +2375,30 @@ void uniform::update()
if (shadersys->curr_render_target)
{
float targetdims[2] = {
static_cast<float>(shadersys->curr_render_target->target_width),
static_cast<float>(shadersys->curr_render_target->target_height) };
float(shadersys->curr_render_target->target_width),
float(shadersys->curr_render_target->target_height) };
m_shader->set_vector("TargetDims", 2, targetdims);
}
break;
}
case CU_TARGET_SCALE:
{
if (shadersys->curr_render_target)
{
float targetscale[2] = {
shadersys->oversampling_enable ? 2.0f : 1.0f,
shadersys->oversampling_enable ? 2.0f : 1.0f };
m_shader->set_vector("TargetScale", 2, targetscale);
}
break;
}
case CU_QUAD_DIMS:
{
if (shadersys->curr_poly)
{
float quaddims[2] = {
// round
static_cast<float>(static_cast<int>(shadersys->curr_poly->prim_width() + 0.5f)),
static_cast<float>(static_cast<int>(shadersys->curr_poly->prim_height() + 0.5f)) };
floor(shadersys->curr_poly->prim_width() + 0.5f),
floor(shadersys->curr_poly->prim_height() + 0.5f) };
m_shader->set_vector("QuadDims", 2, quaddims);
}
break;
@ -2497,7 +2515,7 @@ void uniform::update()
break;
case CU_POST_SHADOW_COUNT:
{
float shadowcount[2] = { static_cast<float>(options->shadow_mask_count_x), static_cast<float>(options->shadow_mask_count_y) };
float shadowcount[2] = { float(options->shadow_mask_count_x), float(options->shadow_mask_count_y) };
m_shader->set_vector("ShadowCount", 2, shadowcount);
break;
}

View File

@ -42,8 +42,10 @@ public:
enum
{
CU_SCREEN_DIMS = 0,
CU_SCREEN_COUNT,
CU_SOURCE_DIMS,
CU_TARGET_DIMS,
CU_TARGET_SCALE,
CU_QUAD_DIMS,
CU_SWAP_XY,

View File

@ -1423,6 +1423,8 @@ void renderer_d3d9::batch_vectors(int vector_count)
float quad_width = 0.0f;
float quad_height = 0.0f;
float target_width = 0.0f;
float target_height = 0.0f;
int vertex_count = vector_count * 6;
int triangle_count = vector_count * 2;
@ -1445,8 +1447,10 @@ void renderer_d3d9::batch_vectors(int vector_count)
case render_primitive::QUAD:
if (PRIMFLAG_GET_VECTORBUF(prim.flags))
{
quad_width = prim.bounds.x1 - prim.bounds.x0;
quad_height = prim.bounds.y1 - prim.bounds.y0;
quad_width = prim.get_quad_width();
quad_height = prim.get_quad_height();
target_width = prim.get_full_quad_width();
target_height = prim.get_full_quad_height();
}
break;
@ -1476,18 +1480,18 @@ void renderer_d3d9::batch_vectors(int vector_count)
((rotation_0 || rotation_90) && orientation_swap_xy) ||
((rotation_180 || rotation_90) && !orientation_swap_xy);
float screen_width = static_cast<float>(this->get_width());
float screen_height = static_cast<float>(this->get_height());
float screen_width = float(this->get_width());
float screen_height = float(this->get_height());
float half_screen_width = screen_width * 0.5f;
float half_screen_height = screen_height * 0.5f;
float screen_swap_x_factor = 1.0f / screen_width * screen_height;
float screen_swap_y_factor = 1.0f / screen_height * screen_width;
float screen_quad_ratio_x = screen_width / quad_width;
float screen_quad_ratio_y = screen_height / quad_height;
float screen_target_ratio_x = screen_width / target_width;
float screen_target_ratio_y = screen_height / target_height;
if (swap_xy)
{
std::swap(screen_quad_ratio_x, screen_quad_ratio_y);
std::swap(screen_target_ratio_x, screen_target_ratio_y);
}
for (int batchindex = 0; batchindex < m_batchindex; batchindex++)
@ -1513,9 +1517,9 @@ void renderer_d3d9::batch_vectors(int vector_count)
m_vectorbatch[batchindex].x -= half_screen_width;
m_vectorbatch[batchindex].y -= half_screen_height;
// correct screen/quad ratio (vectors are created in screen coordinates and have to be adjusted for texture corrdinates of the quad)
m_vectorbatch[batchindex].x *= screen_quad_ratio_x;
m_vectorbatch[batchindex].y *= screen_quad_ratio_y;
// correct screen/target ratio (vectors are created in screen coordinates and have to be adjusted for texture corrdinates of the target)
m_vectorbatch[batchindex].x *= screen_target_ratio_x;
m_vectorbatch[batchindex].y *= screen_target_ratio_y;
// un-center
m_vectorbatch[batchindex].x += half_screen_width;
@ -1668,10 +1672,10 @@ void renderer_d3d9::draw_line(const render_primitive &prim)
vertex[0].u0 = start.c.x;
vertex[0].v0 = start.c.y;
vertex[2].u0 = stop.c.x;
vertex[2].v0 = start.c.y;
vertex[1].u0 = start.c.x;
vertex[1].v0 = stop.c.y;
vertex[2].u0 = stop.c.x;
vertex[2].v0 = start.c.y;
vertex[3].u0 = stop.c.x;
vertex[3].v0 = stop.c.y;
@ -1703,7 +1707,6 @@ void renderer_d3d9::draw_line(const render_primitive &prim)
void renderer_d3d9::draw_quad(const render_primitive &prim)
{
texture_info *texture = m_texture_manager->find_texinfo(&prim.texture, prim.flags);
if (texture == nullptr)
{
texture = get_default_texture();
@ -1712,7 +1715,9 @@ void renderer_d3d9::draw_quad(const render_primitive &prim)
// get a pointer to the vertex buffer
vertex *vertex = mesh_alloc(4);
if (vertex == nullptr)
{
return;
}
// fill in the vertexes clockwise
vertex[0].x = prim.bounds.x0;
@ -1723,8 +1728,8 @@ void renderer_d3d9::draw_quad(const render_primitive &prim)
vertex[2].y = prim.bounds.y1;
vertex[3].x = prim.bounds.x1;
vertex[3].y = prim.bounds.y1;
float width = prim.bounds.x1 - prim.bounds.x0;
float height = prim.bounds.y1 - prim.bounds.y0;
float quad_width = prim.get_quad_width();
float quad_height = prim.get_quad_height();
// set the texture coordinates
if (texture != nullptr)
@ -1761,7 +1766,7 @@ void renderer_d3d9::draw_quad(const render_primitive &prim)
}
// now add a polygon entry
m_poly[m_numpolys].init(D3DPT_TRIANGLESTRIP, 2, 4, prim.flags, texture, D3DTOP_MODULATE, width, height);
m_poly[m_numpolys].init(D3DPT_TRIANGLESTRIP, 2, 4, prim.flags, texture, D3DTOP_MODULATE, quad_width, quad_height);
m_numpolys++;
}