- Tried adding bilinear filtering support for paletted textures, but the

shader seems to be producing crappy output, so it's disabled for now.
  Specifically, it produces distorted output at regular intervals for
  textures that aren't power-of-2-sized, and it's still doing visible
  filtering when the texture is rendered at its original size, so
  obviously it's not doing something right.
- Fixed the use of power-of-2-sized native textures for smaller game
  textures again.
- Fixed: D3DFB did not restore all the state it needed to after resetting
  the device.
- Fixed: R_DrawTopBorder() must clip itself around the 3D view, since it's
  now drawn later.
- With full software rendering, palette flashes once again effect the whole
  screen.

Changes I neglected to put in the previous commit log:

- Moved the view border drawing into the 2D mode part. When using Begin2D()
  now, the only part of the software buffer that gets updated to the screen
  is the part with the actual 3D scene and only if you tell it to.
- Fixed a D3D memory leak on every frame in windowed mode and the same thing
  for the screen wipes. Note to self: If it's an interface, be sure to
  Release it, because it will be AddRef'ed before being returned to you.
- Moved the BlendView() call out of FBaseStatusBar::Draw() so that it can be
  applied before copying the 3D scene to the screen underneath the 2D parts.
- Restored the console's darkening level to its old table-based amount.
- Fixed D3DFB::SetColorOverlay()'s incorrect calculations.
- Fixed the D3D screen wipes for letterboxed modes.

SVN r662 (trunk)
This commit is contained in:
Randy Heit 2008-01-03 05:39:36 +00:00
parent 59c8faa7df
commit 5d9d2a9088
9 changed files with 347 additions and 168 deletions

View file

@ -1,5 +1,24 @@
January 2, 2008
- Tried adding bilinear filtering support for paletted textures, but the
shader seems to be producing crappy output, so it's disabled for now.
Specifically, it produces distorted output at regular intervals for
textures that aren't power-of-2-sized, and it's still doing visible
filtering when the texture is rendered at its original size, so
obviously it's not doing something right.
- Fixed the use of power-of-2-sized native textures for smaller game
textures again.
- Fixed: D3DFB did not restore all the state it needed to after resetting
the device.
- Fixed: R_DrawTopBorder() must clip itself around the 3D view, since it's
now drawn later.
- With full software rendering, palette flashes once again effect the whole
screen.
January 1, 2008
- The mouse is no longer grabbed at all unless you're actually in a level.
- The mouse is no longer grabbed at all unless you're actually in a level,
since I couldn't think of any reason why it should be grabbed at any other
time. (This only applies to windowed mode, where it makes sense to let the
OS have control of the pointer.)
- Moved the view border drawing into the 2D mode part. When using Begin2D()
now, the only part of the software buffer that gets updated to the screen
is the part with the actual 3D scene and only if you tell it to.

View file

@ -807,6 +807,7 @@ void D_PageDrawer (void)
DTA_VirtualWidth, Page->GetWidth(),
DTA_VirtualHeight, Page->GetHeight(),
DTA_Masked, false,
DTA_BilinearFilter, true,
TAG_DONE);
screen->FillBorder (NULL);
}

View file

@ -1489,12 +1489,14 @@ void R_DrawTopBorder ()
if (realviewwidth == SCREENWIDTH)
return;
R_DrawBorder (0, 0, SCREENWIDTH, 34);
offset = gameinfo.border->offset;
size = gameinfo.border->size;
if (viewwindowy < 35)
if (viewwindowy < 34)
{
R_DrawBorder (0, 0, viewwindowx, 34);
R_DrawBorder (viewwindowx, 0, viewwindowx+realviewwidth, viewwindowy);
R_DrawBorder (viewwindowx+realviewwidth, 0, SCREENWIDTH, 34);
p1 = TexMan(gameinfo.border->t);
for (x = viewwindowx; x < viewwindowx + realviewwidth; x += size)
{
@ -1515,6 +1517,10 @@ void R_DrawTopBorder ()
p1 = TexMan(gameinfo.border->tr);
screen->DrawTexture (p1, viewwindowx+realviewwidth, viewwindowy - offset, TAG_DONE);
}
else
{
R_DrawBorder (0, 0, SCREENWIDTH, 34);
}
}

View file

@ -298,6 +298,7 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
parms->keepratio = false;
parms->style = STYLE_Count;
parms->masked = true;
parms->bilinear = false;
parms->x = x << FRACBITS;
parms->y = y << FRACBITS;
@ -514,6 +515,10 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
parms->masked = va_arg (tags, INTBOOL);
break;
case DTA_BilinearFilter:
parms->bilinear = va_arg (tags, INTBOOL);
break;
case DTA_KeepRatio:
parms->keepratio = va_arg (tags, INTBOOL);
break;

View file

@ -101,7 +101,8 @@ enum
DTA_HUDRules, // use fullscreen HUD rules to position and size textures
DTA_KeepRatio, // doesn't adjust screen size for DTA_Virtual* if the aspect ratio is not 4:3
DTA_RenderStyle, // same as render style for actors
DTA_ColorOverlay, // DWORD: ARGB to overlay on top of image. Limited under software.
DTA_ColorOverlay, // DWORD: ARGB to overlay on top of image; limited to black for software
DTA_BilinearFilter, // bool: apply bilinear filtering to the image
// For DrawText calls:
DTA_TextLen, // stop after this many characters, even if \0 not hit
@ -229,6 +230,7 @@ protected:
int virtHeight;
INTBOOL keepratio;
INTBOOL masked;
INTBOOL bilinear;
ERenderStyle style;
};

View file

@ -71,7 +71,7 @@
// MACROS ------------------------------------------------------------------
// The number of vertices the vertex buffer should hold.
#define NUM_VERTS 28
#define NUM_VERTS 12
// TYPES -------------------------------------------------------------------
@ -171,6 +171,7 @@ D3DFB::D3DFB (int width, int height, bool fullscreen)
StencilPaletteTexture = NULL;
ShadedPaletteTexture = NULL;
PalTexShader = NULL;
PalTexBilinearShader = NULL;
PlainShader = NULL;
PlainStencilShader = NULL;
DimShader = NULL;
@ -183,13 +184,13 @@ D3DFB::D3DFB (int width, int height, bool fullscreen)
BlendingRect.top = 0;
BlendingRect.right = FBWidth;
BlendingRect.bottom = FBHeight;
UseBlendingRect = false;
In2D = 0;
Palettes = NULL;
Textures = NULL;
Accel2D = true;
GatheringWipeScreen = false;
ScreenWipe = NULL;
InScene = false;
Gamma = 1.0;
FlashConstants[0][3] = FlashConstants[0][2] = FlashConstants[0][1] = FlashConstants[0][0] = 0;
@ -246,12 +247,7 @@ D3DFB::D3DFB (int width, int height, bool fullscreen)
if (D3DDevice != NULL)
{
CreateResources ();
// Be sure we know what the alpha blend is
D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
AlphaBlendEnabled = FALSE;
AlphaSrcBlend = D3DBLEND(0);
AlphaDestBlend = D3DBLEND(0);
SetInitialState ();
}
}
@ -264,6 +260,29 @@ D3DFB::~D3DFB ()
}
}
// Called after initial device creation and reset, when everything is set
// to D3D's defaults.
void D3DFB::SetInitialState()
{
D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
AlphaBlendEnabled = FALSE;
AlphaSrcBlend = D3DBLEND(0);
AlphaDestBlend = D3DBLEND(0);
CurPixelShader = NULL;
memset(Constant, 0, sizeof(Constant));
Texture[0] = NULL;
Texture[1] = NULL;
D3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
D3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
SetGamma (Gamma);
OldRenderTarget = NULL;
}
void D3DFB::FillPresentParameters (D3DPRESENT_PARAMETERS *pp, bool fullscreen, bool vsync)
{
memset (pp, 0, sizeof(*pp));
@ -327,13 +346,15 @@ bool D3DFB::CreateResources ()
Printf ("Windowed mode gamma will not work.\n");
GammaFixerShader = NULL;
}
if (FAILED(D3DDevice->CreatePixelShader(PalTexBilinearDef, &PalTexBilinearShader)))
{
PalTexBilinearShader = PalTexShader;
}
if (FAILED(D3DDevice->CreatePixelShader (BurnShaderDef, &BurnShader)))
{
Printf ("Burn screenwipe will not work in D3D mode.\n");
BurnShader = NULL;
}
CurPixelShader = NULL;
memset(Constant, 0, sizeof(Constant));
if (!CreateFBTexture() ||
!CreatePaletteTexture() ||
!CreateStencilPaletteTexture() ||
@ -345,9 +366,6 @@ bool D3DFB::CreateResources ()
{
return false;
}
SetGamma (Gamma);
OldRenderTarget = NULL;
return true;
}
@ -372,6 +390,14 @@ void D3DFB::ReleaseResources ()
ShadedPaletteTexture->Release();
ShadedPaletteTexture = NULL;
}
if (PalTexBilinearShader != NULL)
{
if (PalTexBilinearShader != PalTexShader)
{
PalTexBilinearShader->Release();
}
PalTexBilinearShader = NULL;
}
if (PalTexShader != NULL)
{
PalTexShader->Release();
@ -457,6 +483,7 @@ bool D3DFB::Reset ()
{
return false;
}
SetInitialState();
return true;
}
@ -587,39 +614,13 @@ bool D3DFB::CreateVertexes ()
bool D3DFB::UploadVertices()
{
float top = GatheringWipeScreen ? -0.5f : LBOffset - 0.5f;
float top = LBOffset - 0.5f;
float right = float(Width) - 0.5f;
float bot = float(Height) + top;
float texright = float(Width) / float(FBWidth);
float texbot = float(Height) / float(FBHeight);
void *pverts;
if ((BlendingRect.left <= 0 && BlendingRect.right >= FBWidth &&
BlendingRect.top <= 0 && BlendingRect.bottom >= FBHeight) ||
BlendingRect.left >= BlendingRect.right ||
BlendingRect.top >= BlendingRect.bottom)
{
// Blending rect covers the whole screen, so only need 4 verts.
FBVERTEX verts[4] =
{
{ -0.5f, top, 0.5f, 1.f, 0.f, 0.f },
{ right, top, 0.5f, 1.f, texright, 0.f },
{ right, bot, 0.5f, 1.f, texright, texbot },
{ -0.5f, bot, 0.5f, 1.f, 0.f, texbot }
};
if (SUCCEEDED(VertexBuffer->Lock(0, sizeof(verts), &pverts, 0)))
{
memcpy (pverts, verts, sizeof(verts));
VertexBuffer->Unlock();
return true;
}
return false;
}
// Only the 3D area of the screen is effected by palette flashes.
// So we create some boxes around it that can be drawn without the
// flash. These include the corners of the view area so I can be
// sure the texture interpolation is consistant. (Well, actually,
// since it's a 1-to-1 pixel mapping, it shouldn't matter.)
float mxl = float(BlendingRect.left) - 0.5f;
float mxr = float(BlendingRect.right) - 0.5f;
float myt = float(BlendingRect.top) + top;
@ -628,56 +629,26 @@ bool D3DFB::UploadVertices()
float tmxr = float(BlendingRect.right) / float(Width) * texright;
float tmyt = float(BlendingRect.top) / float(Height) * texbot;
float tmyb = float(BlendingRect.bottom) / float(Height) * texbot;
/* +-------------------+
| |
+-----+-------+-----+
| | | |
| | | |
| | | |
+-----+-------+-----+
| |
+-------------------+ */
FBVERTEX verts[28] =
FBVERTEX verts[NUM_VERTS] =
{
// The whole screen, for when no blending is happening
// The whole screen
{ -0.5f, top, 0.5f, 1.f, 0.f, 0.f }, // 0
{ right, top, 0.5f, 1.f, texright, 0.f },
{ right, bot, 0.5f, 1.f, texright, texbot },
{ -0.5f, bot, 0.5f, 1.f, 0.f, texbot },
// Left area
{ -0.5f, myt, 0.5f, 1.f, 0.f, tmyt }, // 4
{ mxl, myt, 0.5f, 1.f, tmxl, tmyt },
{ mxl, myb, 0.5f, 1.f, tmxl, tmyb },
{ -0.5f, myb, 0.5f, 1.f, 0.f, tmyb },
// Right area
{ mxr, myt, 0.5f, 1.f, tmxr, tmyt }, // 8
{ right, myt, 0.5f, 1.f, texright, tmyt },
{ right, myb, 0.5f, 1.f, texright, tmyb },
{ mxr, myb, 0.5f, 1.f, tmxr, tmyb },
// Bottom area
{ -0.5f, bot, 0.5f, 1.f, 0.f, texbot }, // 12
{ -0.5f, myb, 0.5f, 1.f, 0.f, tmyb },
{ mxl, myb, 0.5f, 1.f, tmxl, tmyb },
{ mxr, myb, 0.5f, 1.f, tmxr, tmyb },
{ right, myb, 0.5f, 1.f, texright, tmyb },
{ right, bot, 0.5f, 1.f, texright, texbot },
// Top area
{ right, top, 0.5f, 1.f, texright, 0.f }, // 18
{ right, myt, 0.5f, 1.f, texright, tmyt },
{ mxr, myt, 0.5f, 1.f, tmxr, tmyt },
{ mxl, myt, 0.5f, 1.f, tmxl, tmyt },
{ -0.5f, myt, 0.5f, 1.f, 0.f, tmyt },
{ -0.5f, top, 0.5f, 1.f, 0.f, 0.f },
// Middle (blended) area
{ mxl, myt, 0.5f, 1.f, tmxl, tmyt }, // 24
// 3D view part of the screen
{ mxl, myt, 0.5f, 1.f, tmxl, tmyt }, // 4
{ mxr, myt, 0.5f, 1.f, tmxr, tmyt },
{ mxr, myb, 0.5f, 1.f, tmxr, tmyb },
{ mxl, myb, 0.5f, 1.f, tmxl, tmyb }
{ mxl, myb, 0.5f, 1.f, tmxl, tmyb },
// Used when getting the end screen for wipes
{ -0.5f, -0.5f, 0.5f, 1.f, 0.f, 0.f }, // 8
{ right, -0.5f, 0.5f, 1.f, texright, 0.f },
{ right, float(Height) - 0.5f, 0.5f, 1.f, texright, texbot },
{ -0.5f, float(Height) - 0.5f, 0.5f, 1.f, 0.f, texbot },
};
if (SUCCEEDED(VertexBuffer->Lock(0, sizeof(verts), &pverts, 0)))
{
@ -760,10 +731,14 @@ void D3DFB::Update ()
{
if (In2D == 3)
{
DrawRateStuff();
DoWindowedGamma();
D3DDevice->EndScene();
D3DDevice->Present(NULL, NULL, NULL, NULL);
if (InScene)
{
DrawRateStuff();
DoWindowedGamma();
D3DDevice->EndScene();
D3DDevice->Present(NULL, NULL, NULL, NULL);
InScene = false;
}
In2D = 0;
return;
}
@ -803,7 +778,7 @@ void D3DFB::Update ()
}
psgamma[2] = psgamma[1] = psgamma[0] = igamma;
psgamma[3] = 1;
D3DDevice->SetPixelShaderConstantF(4, psgamma, 1);
D3DDevice->SetPixelShaderConstantF(7, psgamma, 1);
NeedPalUpdate = true;
}
@ -828,6 +803,7 @@ void D3DFB::Update ()
DoWindowedGamma();
D3DDevice->EndScene();
D3DDevice->Present(NULL, NULL, NULL, NULL);
InScene = false;
}
unclock (BlitCycles);
@ -888,6 +864,7 @@ void D3DFB::Draw3DPart(bool copy3d)
}
}
DrawLetterbox();
InScene = true;
D3DDevice->BeginScene();
assert(OldRenderTarget == NULL);
if (TempRenderTexture != NULL &&
@ -908,7 +885,7 @@ void D3DFB::Draw3DPart(bool copy3d)
}
SetTexture (0, FBTexture);
SetPaletteTexture(PaletteTexture, 256);
SetPaletteTexture(PaletteTexture, 256, false);
D3DDevice->SetStreamSource (0, VertexBuffer, 0, sizeof(FBVERTEX));
D3DDevice->SetFVF (D3DFVF_FBVERTEX);
D3DDevice->SetPixelShaderConstantF (0, FlashConstants[0], 2);
@ -916,27 +893,7 @@ void D3DFB::Draw3DPart(bool copy3d)
SetAlphaBlend(FALSE);
if (copy3d)
{
if (!UseBlendingRect || FlashConstants[1][0] == 1)
{ // The whole screen as a single quad.
D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 0, 2);
}
else
{ // The screen split up so that only the 3D view is blended.
D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 24, 2); // middle
if (!In2D)
{
// The rest is drawn unblended, so reset the shader constant.
static const float FlashZero[2][4] = { { 0, 0, 0, 0 }, { 1, 1, 1, 1 } };
D3DDevice->SetPixelShaderConstantF (0, FlashZero[0], 2);
memcpy(Constant, FlashZero, sizeof(FlashZero));
D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 4, 2); // left
D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 8, 2); // right
D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 12, 4); // bottom
D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 18, 4); // top
}
}
D3DDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, !test2d ? 0 : OldRenderTarget != NULL ? 8 : 4, 2);
}
}
@ -1079,12 +1036,7 @@ void D3DFB::SetBlendingRect(int x1, int y1, int x2, int y2)
BlendingRect.right = x2;
BlendingRect.bottom = y2;
if (UploadVertices())
{
UseBlendingRect = ((x1 > 0 || x2 < FBWidth || y1 > 0 || y2 < FBHeight)
&& BlendingRect.left < BlendingRect.right
&& BlendingRect.top < BlendingRect.bottom);
}
UploadVertices();
}
}
@ -1165,8 +1117,12 @@ bool D3DTex::Create(IDirect3DDevice9 *D3DDevice)
w = GameTex->GetWidth();
h = GameTex->GetHeight();
#if 1
hr = D3DDevice->CreateTexture(w, h, 1, 0,
GetTexFormat(), D3DPOOL_MANAGED, &Tex, NULL);
#else
hr = E_FAIL;
#endif
if (SUCCEEDED(hr))
{
TX = 1;
@ -1401,7 +1357,6 @@ bool D3DPal::Update()
bool D3DFB::Begin2D(bool copy3d)
{
copy3d = true;
if (!test2d)
{
return false;
@ -1470,6 +1425,10 @@ void D3DFB::Clear (int left, int top, int right, int bottom, int palcolor, uint3
Super::Clear(left, top, right, bottom, palcolor, color);
return;
}
if (!InScene)
{
return;
}
if (palcolor >= 0)
{
color = GPalette.BaseColors[palcolor];
@ -1493,13 +1452,18 @@ void D3DFB::Clear (int left, int top, int right, int bottom, int palcolor, uint3
void D3DFB::Dim (PalEntry color, float amount, int x1, int y1, int w, int h)
{
if (amount <= 0)
{
return;
}
if (In2D < 2)
{
Super::Dim(color, amount, x1, y1, w, h);
return;
}
if (!InScene)
{
return;
}
if (amount >= 1)
{
D3DRECT rect = { x1, y1, x1 + w, y1 + h };
@ -1542,7 +1506,7 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi
DrawParms parms;
if (!ParseDrawTextureTags(img, x, y, tags_first, tags, &parms, true))
if (!InScene || !ParseDrawTextureTags(img, x, y, tags_first, tags, &parms, true))
{
return;
}
@ -1565,17 +1529,17 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi
float v0 = 0.f;
float u1 = tex->TX;
float v1 = tex->TY;
float uscale = 1.f / parms.texwidth / u1;
float vscale = 1.f / parms.texheight / v1 / yscale;
float uscale = 1.f / (parms.texwidth / u1);
float vscale = 1.f / (parms.texheight / v1) / yscale;
if (y0 < parms.uclip)
{
v0 += float(parms.uclip - y0) * vscale;
v0 += (float(parms.uclip) - y0) * vscale;
y0 = float(parms.uclip);
}
if (y1 > parms.dclip)
{
v1 -= float(y1 - parms.dclip) * vscale;
v1 -= (y1 - float(parms.dclip)) * vscale;
y1 = float(parms.dclip);
}
@ -1615,6 +1579,7 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi
{ x0, y1, 0.5f, 1.f, u0, v1 }
};
parms.bilinear = false;
if (!SetStyle(tex, parms))
{
return;
@ -1668,7 +1633,11 @@ bool D3DFB::SetStyle(D3DTex *tex, DrawParms &parms)
if (alpha > 0)
{
SetConstant(1, RPART(parms.fillcolor)/255.f, GPART(parms.fillcolor)/255.f, BPART(parms.fillcolor)/255.f, alpha);
SetPaletteTexture(ShadedPaletteTexture, 256);
SetPaletteTexture(ShadedPaletteTexture, 256, parms.bilinear);
if (parms.bilinear)
{
SetPalTexBilinearConstants(tex);
}
SetAlphaBlend(TRUE, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
return true;
}
@ -1715,8 +1684,11 @@ bool D3DFB::SetStyle(D3DTex *tex, DrawParms &parms)
SetColorOverlay(parms.colorOverlay, 1);
if (fmt == D3DFMT_L8 && !tex->IsGray)
{
SetPaletteTexture(PaletteTexture, 256);
SetPixelShader(PalTexShader);
SetPaletteTexture(PaletteTexture, 256, parms.bilinear);
if (parms.bilinear)
{
SetPalTexBilinearConstants(tex);
}
}
else
{
@ -1734,7 +1706,11 @@ bool D3DFB::SetStyle(D3DTex *tex, DrawParms &parms)
if (parms.remap != NULL)
{
D3DPal *pal = reinterpret_cast<D3DPal *>(parms.remap->GetNative());
SetPaletteTexture(pal->Tex, pal->RoundedPaletteSize);
SetPaletteTexture(pal->Tex, pal->RoundedPaletteSize, parms.bilinear);
if (parms.bilinear)
{
SetPalTexBilinearConstants(tex);
}
}
else if (tex->IsGray)
{
@ -1742,9 +1718,12 @@ bool D3DFB::SetStyle(D3DTex *tex, DrawParms &parms)
}
else
{
SetPaletteTexture(PaletteTexture, 256);
SetPaletteTexture(PaletteTexture, 256, parms.bilinear);
if (parms.bilinear)
{
SetPalTexBilinearConstants(tex);
}
}
SetPixelShader(PalTexShader);
}
else
{
@ -1760,8 +1739,8 @@ bool D3DFB::SetStyle(D3DTex *tex, DrawParms &parms)
BPART(parms.fillcolor)/255.f, alpha);
if (fmt == D3DFMT_L8)
{
SetPaletteTexture(StencilPaletteTexture, 256);
SetPixelShader(PalTexShader);
// Doesn't seem to be much point in allowing bilinear with a stencil
SetPaletteTexture(StencilPaletteTexture, 256, false);
}
else
{
@ -1857,7 +1836,7 @@ void D3DFB::SetTexture(int tnum, IDirect3DTexture9 *texture)
}
}
void D3DFB::SetPaletteTexture(IDirect3DTexture9 *texture, int count)
void D3DFB::SetPaletteTexture(IDirect3DTexture9 *texture, int count, INTBOOL bilinear)
{
if (count == 256 || SM14)
{
@ -1881,5 +1860,27 @@ void D3DFB::SetPaletteTexture(IDirect3DTexture9 *texture, int count)
SetConstant(2, 255 * fcount, 0.5f * fcount, 0, 0);
}
SetTexture(1, texture);
SetPixelShader(PalTexShader);
SetPixelShader(!bilinear ? PalTexShader : PalTexBilinearShader);
}
void D3DFB::SetPalTexBilinearConstants(D3DTex *tex)
{
float con[8];
// Don't bother doing anything if the constants won't be used.
if (PalTexShader == PalTexBilinearShader)
{
return;
}
con[0] = tex->GameTex->GetWidth() / tex->TX;
con[1] = tex->GameTex->GetHeight() / tex->TY;
con[2] = 0;
con[3] = 1 / con[0];
con[4] = 0;
con[5] = 1 / con[1];
con[6] = con[5];
con[7] = con[3];
D3DDevice->SetPixelShaderConstantF(3, con, 2);
}

View file

@ -114,6 +114,152 @@ const DWORD PalTexShader20Def[] =
0x0000ffff
};
// A paletted texture shader that does bilinear filtering -------------------
#if HLSL_SOURCE_CODE
sampler2D Image : register(s0);
sampler2D Palette : register(s1);
float4 Flash : register(c0);
float4 InvFlash : register(c1);
float4 PaletteMod : register(c2);
//#define texture_size_x 512.0f
//#define texture_size_y 256.0f
//#define texel_size_x 1.0f / 512.0f
//#define texel_size_y 1.0f / 256.0f
// texture_size_x, texture_size_y, 0, texel_size_x
float4 size_a : register(c3);
// 0, texel_size_y, texel_size_y, texel_size_x
float4 size_b : register(c4);
float4 main (float2 texCoord : TEXCOORD0) : COLOR
{
float2 f = frac (texCoord.xy * size_a/*float2(texture_size_x, texture_size_y)*/);
float4 t00 = tex2D(Image, texCoord);
float4 t10 = tex2D(Image, texCoord + size_a.wz/*float2(texel_size_x, 0)*/);
t00.x = t00.x * PaletteMod.x + PaletteMod.y;
t10.x = t10.x * PaletteMod.x + PaletteMod.y;
float4 c00 = tex2D(Palette, t00);
float4 c10 = tex2D(Palette, t10);
float4 cA = lerp(c00, c10, f.x);
float4 t01 = tex2D(Image, texCoord + size_b.xy/*float2(0, texel_size_y)*/);
float4 t11 = tex2D(Image, texCoord + size_b.wz/*float2(texel_size_x, texel_size_y)*/);
t01.x = t01.x * PaletteMod.x + PaletteMod.y;
t11.x = t11.x * PaletteMod.x + PaletteMod.y;
float4 c01 = tex2D(Palette, t01);
float4 c11 = tex2D(Palette, t11);
float4 cB = lerp(c01, c11, f.x);
return Flash + lerp(cA, cB, f.y) * InvFlash;
}
#elif SHADER_ASSEMBLY_CODE
//
// Generated by Microsoft (R) HLSL Shader Compiler 9.19.949.2111
//
// fxc paltex_bilinear.ps /Tps_2_0 /VnPalTexBilinearDef /Fhpaltex_bilinea
//
//
// Parameters:
//
// float4 Flash;
// sampler2D Image;
// float4 InvFlash;
// sampler2D Palette;
// float4 PaletteMod;
// float4 size_a;
// float4 size_b;
//
//
// Registers:
//
// Name Reg Size
// ------------ ----- ----
// Flash c0 1
// InvFlash c1 1
// PaletteMod c2 1
// size_a c3 1
// size_b c4 1
// Image s0 1
// Palette s1 1
//
ps_2_0
dcl t0.xy
dcl_2d s0
dcl_2d s1
add r0.xy, t0, c4
add r1.xy, t0, c4.wzyx
add r2.xy, t0, c3.wzyx
texld r0, r0, s0
texld r1, r1, s0
texld r2, r2, s0
texld r3, t0, s0
mad r0.x, r0.x, c2.x, c2.y
mad r1.x, r1.x, c2.x, c2.y
mad r2.x, r2.x, c2.x, c2.y
mad r3.x, r3.x, c2.x, c2.y
texld r0, r0, s1
texld r1, r1, s1
texld r2, r2, s1
texld r3, r3, s1
mul r4.xy, t0, c3
frc r4.xy, r4
lrp r5, r4.x, r1, r0
lrp r0, r4.x, r2, r3
lrp r1, r4.y, r5, r0
mov r0, c1
mad r0, r1, r0, c0
mov oC0, r0
// approximately 23 instruction slots used (8 texture, 15 arithmetic)
#endif
const DWORD PalTexBilinearDef[] =
{
0xffff0200, 0x0050fffe, 0x42415443, 0x0000001c, 0x00000109, 0xffff0200,
0x00000007, 0x0000001c, 0x20000100, 0x00000102, 0x000000a8, 0x00000002,
0x00020001, 0x000000b0, 0x00000000, 0x000000c0, 0x00000003, 0x00020001,
0x000000c8, 0x00000000, 0x000000d8, 0x00010002, 0x00060001, 0x000000b0,
0x00000000, 0x000000e1, 0x00010003, 0x00060001, 0x000000c8, 0x00000000,
0x000000e9, 0x00020002, 0x000a0001, 0x000000b0, 0x00000000, 0x000000f4,
0x00030002, 0x000e0001, 0x000000b0, 0x00000000, 0x000000fb, 0x00040002,
0x00120001, 0x000000b0, 0x00000000, 0x73616c46, 0xabab0068, 0x00030001,
0x00040001, 0x00000001, 0x00000000, 0x67616d49, 0xabab0065, 0x000c0004,
0x00010001, 0x00000001, 0x00000000, 0x46766e49, 0x6873616c, 0x6c615000,
0x65747465, 0x6c615000, 0x65747465, 0x00646f4d, 0x657a6973, 0x7300615f,
0x5f657a69, 0x73700062, 0x305f325f, 0x63694d00, 0x6f736f72, 0x28207466,
0x48202952, 0x204c534c, 0x64616853, 0x43207265, 0x69706d6f, 0x2072656c,
0x39312e39, 0x3934392e, 0x3131322e, 0xabab0031, 0x0200001f, 0x80000000,
0xb0030000, 0x0200001f, 0x90000000, 0xa00f0800, 0x0200001f, 0x90000000,
0xa00f0801, 0x03000002, 0x80030000, 0xb0e40000, 0xa0e40004, 0x03000002,
0x80030001, 0xb0e40000, 0xa01b0004, 0x03000002, 0x80030002, 0xb0e40000,
0xa01b0003, 0x03000042, 0x800f0000, 0x80e40000, 0xa0e40800, 0x03000042,
0x800f0001, 0x80e40001, 0xa0e40800, 0x03000042, 0x800f0002, 0x80e40002,
0xa0e40800, 0x03000042, 0x800f0003, 0xb0e40000, 0xa0e40800, 0x04000004,
0x80010000, 0x80000000, 0xa0000002, 0xa0550002, 0x04000004, 0x80010001,
0x80000001, 0xa0000002, 0xa0550002, 0x04000004, 0x80010002, 0x80000002,
0xa0000002, 0xa0550002, 0x04000004, 0x80010003, 0x80000003, 0xa0000002,
0xa0550002, 0x03000042, 0x800f0000, 0x80e40000, 0xa0e40801, 0x03000042,
0x800f0001, 0x80e40001, 0xa0e40801, 0x03000042, 0x800f0002, 0x80e40002,
0xa0e40801, 0x03000042, 0x800f0003, 0x80e40003, 0xa0e40801, 0x03000005,
0x80030004, 0xb0e40000, 0xa0e40003, 0x02000013, 0x80030004, 0x80e40004,
0x04000012, 0x800f0005, 0x80000004, 0x80e40001, 0x80e40000, 0x04000012,
0x800f0000, 0x80000004, 0x80e40002, 0x80e40003, 0x04000012, 0x800f0001,
0x80550004, 0x80e40005, 0x80e40000, 0x02000001, 0x800f0000, 0xa0e40001,
0x04000004, 0x800f0000, 0x80e40001, 0x80e40000, 0xa0e40000, 0x02000001,
0x800f0800, 0x80e40000, 0x0000ffff
};
// A shader that doesn't look up colors from a palette. ---------------------
// Can be used for RGB textures.
@ -277,7 +423,7 @@ const DWORD DimShaderDef[] =
#if HLSL_SOURCE_CODE
sampler2D Image : register(s0);
float4 Gamma : register(c4);
float4 Gamma : register(c7);
float4 main (float2 texCoord : TEXCOORD0) : COLOR
{
@ -287,9 +433,9 @@ float4 main (float2 texCoord : TEXCOORD0) : COLOR
}
#elif SHADER_ASSEMBLY_CODE
//
// Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000
// Generated by Microsoft (R) HLSL Shader Compiler 9.19.949.2111
//
// fxc gammafixer.ps /Tps_2_0 /VnGammaFixerDef /Fh
// fxc gammafixer.ps /Tps_2_0 /VnGammaFixerDef /Fhgammafixer.h
//
//
// Parameters:
@ -302,7 +448,7 @@ float4 main (float2 texCoord : TEXCOORD0) : COLOR
//
// Name Reg Size
// ------------ ----- ----
// Gamma c4 1
// Gamma c7 1
// Image s0 1
//
@ -310,13 +456,13 @@ float4 main (float2 texCoord : TEXCOORD0) : COLOR
dcl t0.xy
dcl_2d s0
texld r0, t0, s0
log r0.x, r0.x
log r0.y, r0.y
log r0.z, r0.z
mul r0.xyz, r0, c4
exp r0.x, r0.x
exp r0.y, r0.y
exp r0.z, r0.z
log r1.x, r0.x
log r1.y, r0.y
log r1.z, r0.z
mul r1.xyz, r1, c7
exp r0.x, r1.x
exp r0.y, r1.y
exp r0.z, r1.z
mov oC0, r0
// approximately 9 instruction slots used (1 texture, 8 arithmetic)
@ -324,20 +470,20 @@ float4 main (float2 texCoord : TEXCOORD0) : COLOR
const DWORD GammaFixerDef[] =
{
0xffff0200, 0x002dfffe, 0x42415443, 0x0000001c, 0x0000007b, 0xffff0200,
0x00000002, 0x0000001c, 0x00000100, 0x00000074, 0x00000044, 0x00040002,
0x00020001, 0x0000004c, 0x00000000, 0x0000005c, 0x00000003, 0x00000001,
0xffff0200, 0x002cfffe, 0x42415443, 0x0000001c, 0x0000007b, 0xffff0200,
0x00000002, 0x0000001c, 0x20000100, 0x00000074, 0x00000044, 0x00070002,
0x001e0001, 0x0000004c, 0x00000000, 0x0000005c, 0x00000003, 0x00020001,
0x00000064, 0x00000000, 0x6d6d6147, 0xabab0061, 0x00030001, 0x00040001,
0x00000001, 0x00000000, 0x67616d49, 0xabab0065, 0x000c0004, 0x00010001,
0x00000001, 0x00000000, 0x325f7370, 0x4d00305f, 0x6f726369, 0x74666f73,
0x29522820, 0x44334420, 0x53203958, 0x65646168, 0x6f432072, 0x6c69706d,
0x39207265, 0x2e35312e, 0x2e393737, 0x30303030, 0xababab00, 0x0200001f,
0x80000000, 0xb0030000, 0x0200001f, 0x90000000, 0xa00f0800, 0x03000042,
0x800f0000, 0xb0e40000, 0xa0e40800, 0x0200000f, 0x80010000, 0x80000000,
0x0200000f, 0x80020000, 0x80550000, 0x0200000f, 0x80040000, 0x80aa0000,
0x03000005, 0x80070000, 0x80e40000, 0xa0e40004, 0x0200000e, 0x80010000,
0x80000000, 0x0200000e, 0x80020000, 0x80550000, 0x0200000e, 0x80040000,
0x80aa0000, 0x02000001, 0x800f0800, 0x80e40000, 0x0000ffff
0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970,
0x2e392072, 0x392e3931, 0x322e3934, 0x00313131, 0x0200001f, 0x80000000,
0xb0030000, 0x0200001f, 0x90000000, 0xa00f0800, 0x03000042, 0x800f0000,
0xb0e40000, 0xa0e40800, 0x0200000f, 0x80010001, 0x80000000, 0x0200000f,
0x80020001, 0x80550000, 0x0200000f, 0x80040001, 0x80aa0000, 0x03000005,
0x80070001, 0x80e40001, 0xa0e40007, 0x0200000e, 0x80010000, 0x80000001,
0x0200000e, 0x80020000, 0x80550001, 0x0200000e, 0x80040000, 0x80aa0001,
0x02000001, 0x800f0800, 0x80e40000, 0x0000ffff
};
// The shader used by the burn effect screen wipe ---------------------------

View file

@ -262,7 +262,6 @@ bool D3DFB::WipeStartScreen(int type)
// Even fullscreen will render to the TempRenderTexture, so we can have
// a copy of the new screen readily available.
GatheringWipeScreen = true;
UploadVertices();
return true;
}
@ -338,7 +337,6 @@ bool D3DFB::WipeDo(int ticks)
if (GatheringWipeScreen)
{ // This is the first time we've been called for this wipe.
GatheringWipeScreen = false;
UploadVertices();
if (OldRenderTarget == NULL)
{
@ -349,6 +347,7 @@ bool D3DFB::WipeDo(int ticks)
else
{ // This is the second or later time we've been called for this wipe.
D3DDevice->BeginScene();
InScene = true;
}
if (OldRenderTarget != NULL)
{
@ -468,7 +467,6 @@ bool D3DFB::Wiper_Crossfade::Run(int ticks, D3DFB *fb)
fb->SetConstant(0, 0, 0, 0, clamp(Clock / 32.f, 0.f, 1.f));
fb->SetConstant(1, 1, 1, 1, 0);
fb->SetPixelShader(fb->PlainShader);
// FIXME: The FinalWipeScreen gets junk at the top in letterbox modes.
fb->D3DDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
return Clock >= 32;
@ -681,12 +679,9 @@ bool D3DFB::Wiper_Burn::Run(int ticks, D3DFB *fb)
fb->SetAlphaBlend(TRUE, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
fb->SetPixelShader(fb->BurnShader);
fb->D3DDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
fb->D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
fb->D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
fb->D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts, sizeof(BURNVERTEX));
fb->D3DDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
fb->D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
fb->D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
fb->D3DDevice->SetFVF(D3DFVF_FBVERTEX);
// The fire may not always stabilize, so the wipe is forced to end
// after an arbitrary maximum time.

View file

@ -252,6 +252,7 @@ private:
friend class D3DTex;
friend class D3DPal;
void SetInitialState();
bool CreateResources();
void ReleaseResources();
bool CreateFBTexture();
@ -278,7 +279,8 @@ private:
void SetConstant(int cnum, float r, float g, float b, float a);
void SetPixelShader(IDirect3DPixelShader9 *shader);
void SetTexture(int tnum, IDirect3DTexture9 *texture);
void SetPaletteTexture(IDirect3DTexture9 *texture, int count);
void SetPaletteTexture(IDirect3DTexture9 *texture, int count, INTBOOL bilinear);
void SetPalTexBilinearConstants(D3DTex *texture);
BOOL AlphaBlendEnabled;
D3DBLEND AlphaSrcBlend;
@ -303,8 +305,8 @@ private:
int FBWidth, FBHeight;
bool VSync;
RECT BlendingRect;
bool UseBlendingRect;
int In2D;
bool InScene;
bool SM14;
bool GatheringWipeScreen;
D3DPal *Palettes;
@ -317,12 +319,14 @@ private:
IDirect3DTexture9 *PaletteTexture;
IDirect3DTexture9 *StencilPaletteTexture;
IDirect3DTexture9 *ShadedPaletteTexture;
IDirect3DPixelShader9 *PalTexShader;
IDirect3DPixelShader9 *PalTexShader, *PalTexBilinearShader;
IDirect3DPixelShader9 *PlainShader;
IDirect3DPixelShader9 *PlainStencilShader;
IDirect3DPixelShader9 *DimShader;
IDirect3DPixelShader9 *GammaFixerShader;
IDirect3DPixelShader9 *BurnShader;
IDirect3DSurface9 *OldRenderTarget;
IDirect3DTexture9 *InitialWipeScreen, *FinalWipeScreen;