mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-09-09 22:32:57 +02:00
- Automatic texture filtering should be ok now, occasionally point filtering was used. Tested it on the ps2 and figured with no mip levels LoD and minification settings are just ignored altogether. - Also run a few tests on the gather instruction with the reference rasterizer and found a fatal flaw with it. It returns the four samples for bilinear sampling (in a funny order, which isn't documented of course, x = bl, y = br, z = tr, w = tl), but there is no way to guess which four were selected exactly. Due to some hidden rounding error it might grab different texels than I would when calculating the position of the upper-left texel, of which the fractional part is be used for the interpolation. When the texel positions do not match it leaves annoying discontinuity errors. Oh well... git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1571 96395faa-99c1-11dd-bbfe-3dabce05a288
444 lines
17 KiB
C++
444 lines
17 KiB
C++
/*
|
|
* Copyright (C) 2007-2009 Gabest
|
|
* http://www.gabest.org
|
|
*
|
|
* This Program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This Program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with GNU Make; see the file COPYING. If not, write to
|
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
* http://www.gnu.org/copyleft/gpl.html
|
|
*
|
|
*/
|
|
|
|
#include "stdafx.h"
|
|
#include "GSTextureFX9.h"
|
|
#include "resource.h"
|
|
|
|
GSTextureFX9::GSTextureFX9()
|
|
{
|
|
}
|
|
|
|
GSTextureFX9::~GSTextureFX9()
|
|
{
|
|
for_each(m_mskfix.begin(), m_mskfix.end(), delete_second());
|
|
}
|
|
|
|
bool GSTextureFX9::Create(GSDevice* dev)
|
|
{
|
|
if(!__super::Create(dev))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// create layout
|
|
|
|
VSSelector sel;
|
|
VSConstantBuffer cb;
|
|
|
|
SetupVS(sel, &cb);
|
|
|
|
//
|
|
|
|
return true;
|
|
}
|
|
|
|
GSTexture* GSTextureFX9::CreateMskFix(uint32 size, uint32 msk, uint32 fix)
|
|
{
|
|
GSTexture* t = NULL;
|
|
|
|
uint32 hash = (size << 20) | (msk << 10) | fix;
|
|
|
|
hash_map<uint32, GSTexture*>::iterator i = m_mskfix.find(hash);
|
|
|
|
if(i != m_mskfix.end())
|
|
{
|
|
t = i->second;
|
|
}
|
|
else
|
|
{
|
|
t = m_dev->CreateTexture(size, 1, D3DFMT_R32F);
|
|
|
|
if(t)
|
|
{
|
|
GSTexture::GSMap m;
|
|
|
|
if(t->Map(m))
|
|
{
|
|
for(uint32 i = 0; i < size; i++)
|
|
{
|
|
((float*)m.bits)[i] = (float)((i & msk) | fix) / size;
|
|
}
|
|
|
|
t->Unmap();
|
|
}
|
|
|
|
m_mskfix[hash] = t;
|
|
}
|
|
}
|
|
|
|
return t;
|
|
}
|
|
|
|
void GSTextureFX9::SetupIA(const void* vertices, int count, int prim)
|
|
{
|
|
GSDevice9* dev = (GSDevice9*)m_dev;
|
|
|
|
dev->IASetVertexBuffer(vertices, sizeof(GSVertexHW9), count);
|
|
dev->IASetInputLayout(m_il);
|
|
dev->IASetPrimitiveTopology((D3DPRIMITIVETYPE)prim);
|
|
}
|
|
|
|
void GSTextureFX9::SetupVS(VSSelector sel, const VSConstantBuffer* cb)
|
|
{
|
|
GSDevice9* dev = (GSDevice9*)m_dev;
|
|
|
|
hash_map<uint32, CComPtr<IDirect3DVertexShader9> >::const_iterator i = m_vs.find(sel);
|
|
|
|
if(i == m_vs.end())
|
|
{
|
|
string str[4];
|
|
|
|
str[0] = format("%d", sel.bppz);
|
|
str[1] = format("%d", sel.tme);
|
|
str[2] = format("%d", sel.fst);
|
|
str[3] = format("%d", sel.logz);
|
|
|
|
D3DXMACRO macro[] =
|
|
{
|
|
{"VS_BPPZ", str[0].c_str()},
|
|
{"VS_TME", str[1].c_str()},
|
|
{"VS_FST", str[2].c_str()},
|
|
{"VS_LOGZ", str[3].c_str()},
|
|
{NULL, NULL},
|
|
};
|
|
|
|
static const D3DVERTEXELEMENT9 layout[] =
|
|
{
|
|
{0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
|
|
{0, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
|
|
{0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1},
|
|
{0, 16, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
|
|
D3DDECL_END()
|
|
};
|
|
|
|
CComPtr<IDirect3DVertexDeclaration9> il;
|
|
CComPtr<IDirect3DVertexShader9> vs;
|
|
|
|
dev->CompileShader(IDR_TFX_FX, "vs_main", macro, &vs, layout, countof(layout), &il);
|
|
|
|
if(m_il == NULL)
|
|
{
|
|
m_il = il;
|
|
}
|
|
|
|
m_vs[sel] = vs;
|
|
|
|
i = m_vs.find(sel);
|
|
}
|
|
|
|
dev->VSSetShader(i->second, (const float*)cb, sizeof(*cb) / sizeof(GSVector4));
|
|
}
|
|
|
|
void GSTextureFX9::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel)
|
|
{
|
|
GSDevice9* dev = (GSDevice9*)m_dev;
|
|
|
|
if(cb->WH.z > 0 && cb->WH.w > 0 && (sel.wms == 3 || sel.wmt == 3))
|
|
{
|
|
GSVector4i size(cb->WH);
|
|
|
|
if(sel.wms == 3)
|
|
{
|
|
if(GSTexture* t = CreateMskFix(size.z, cb->MskFix.x, cb->MskFix.z))
|
|
{
|
|
(*dev)->SetTexture(2, *(GSTexture9*)t);
|
|
}
|
|
}
|
|
|
|
if(sel.wmt == 3)
|
|
{
|
|
if(GSTexture* t = CreateMskFix(size.w, cb->MskFix.y, cb->MskFix.w))
|
|
{
|
|
(*dev)->SetTexture(3, *(GSTexture9*)t);
|
|
}
|
|
}
|
|
}
|
|
|
|
hash_map<uint32, CComPtr<IDirect3DPixelShader9> >::const_iterator i = m_ps.find(sel);
|
|
|
|
if(i == m_ps.end())
|
|
{
|
|
string str[12];
|
|
|
|
str[0] = format("%d", sel.fst);
|
|
str[1] = format("%d", sel.wms);
|
|
str[2] = format("%d", sel.wmt);
|
|
str[3] = format("%d", sel.fmt);
|
|
str[4] = format("%d", sel.aem);
|
|
str[5] = format("%d", sel.tfx);
|
|
str[6] = format("%d", sel.tcc);
|
|
str[7] = format("%d", sel.atst);
|
|
str[8] = format("%d", sel.fog);
|
|
str[9] = format("%d", sel.clr1);
|
|
str[10] = format("%d", sel.rt);
|
|
str[11] = format("%d", sel.ltf);
|
|
|
|
D3DXMACRO macro[] =
|
|
{
|
|
{"PS_FST", str[0].c_str()},
|
|
{"PS_WMS", str[1].c_str()},
|
|
{"PS_WMT", str[2].c_str()},
|
|
{"PS_FMT", str[3].c_str()},
|
|
{"PS_AEM", str[4].c_str()},
|
|
{"PS_TFX", str[5].c_str()},
|
|
{"PS_TCC", str[6].c_str()},
|
|
{"PS_ATST", str[7].c_str()},
|
|
{"PS_FOG", str[8].c_str()},
|
|
{"PS_CLR1", str[9].c_str()},
|
|
{"PS_RT", str[10].c_str()},
|
|
{"PS_LTF", str[11].c_str()},
|
|
{NULL, NULL},
|
|
};
|
|
|
|
CComPtr<IDirect3DPixelShader9> ps;
|
|
|
|
dev->CompileShader(IDR_TFX_FX, "ps_main", macro, &ps);
|
|
|
|
m_ps[sel] = ps;
|
|
|
|
i = m_ps.find(sel);
|
|
}
|
|
|
|
dev->PSSetShader(i->second, (const float*)cb, sizeof(*cb) / sizeof(GSVector4));
|
|
|
|
Direct3DSamplerState9* ss = NULL;
|
|
|
|
if(sel.tfx != 4)
|
|
{
|
|
if(!(sel.fmt < 3 && sel.wms < 3 && sel.wmt < 3))
|
|
{
|
|
ssel.ltf = 0;
|
|
}
|
|
|
|
hash_map<uint32, Direct3DSamplerState9* >::const_iterator i = m_ps_ss.find(ssel);
|
|
|
|
if(i != m_ps_ss.end())
|
|
{
|
|
ss = i->second;
|
|
}
|
|
else
|
|
{
|
|
ss = new Direct3DSamplerState9();
|
|
|
|
memset(ss, 0, sizeof(*ss));
|
|
|
|
ss->FilterMin[0] = ssel.ltf ? D3DTEXF_LINEAR : D3DTEXF_POINT;
|
|
ss->FilterMag[0] = ssel.ltf ? D3DTEXF_LINEAR : D3DTEXF_POINT;
|
|
ss->FilterMin[1] = D3DTEXF_POINT;
|
|
ss->FilterMag[1] = D3DTEXF_POINT;
|
|
|
|
ss->AddressU = ssel.tau ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP;
|
|
ss->AddressV = ssel.tav ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP;
|
|
|
|
m_ps_ss[ssel] = ss;
|
|
}
|
|
}
|
|
|
|
dev->PSSetSamplerState(ss);
|
|
}
|
|
|
|
void GSTextureFX9::SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix)
|
|
{
|
|
GSDevice9* dev = (GSDevice9*)m_dev;
|
|
|
|
Direct3DDepthStencilState9* dss = NULL;
|
|
|
|
hash_map<uint32, Direct3DDepthStencilState9*>::const_iterator i = m_om_dss.find(dssel);
|
|
|
|
if(i == m_om_dss.end())
|
|
{
|
|
dss = new Direct3DDepthStencilState9();
|
|
|
|
memset(dss, 0, sizeof(*dss));
|
|
|
|
if(dssel.date || dssel.fba)
|
|
{
|
|
dss->StencilEnable = true;
|
|
dss->StencilReadMask = 1;
|
|
dss->StencilWriteMask = 2;
|
|
dss->StencilFunc = dssel.date ? D3DCMP_EQUAL : D3DCMP_ALWAYS;
|
|
dss->StencilPassOp = dssel.fba ? D3DSTENCILOP_REPLACE : D3DSTENCILOP_KEEP;
|
|
dss->StencilFailOp = dssel.fba ? D3DSTENCILOP_ZERO : D3DSTENCILOP_KEEP;
|
|
dss->StencilDepthFailOp = dssel.fba ? D3DSTENCILOP_ZERO : D3DSTENCILOP_KEEP;
|
|
dss->StencilRef = 3;
|
|
}
|
|
|
|
if(dssel.ztst != ZTST_ALWAYS || dssel.zwe)
|
|
{
|
|
static const D3DCMPFUNC ztst[] =
|
|
{
|
|
D3DCMP_NEVER,
|
|
D3DCMP_ALWAYS,
|
|
D3DCMP_GREATEREQUAL,
|
|
D3DCMP_GREATER
|
|
};
|
|
|
|
dss->DepthEnable = true;
|
|
dss->DepthWriteMask = dssel.zwe;
|
|
dss->DepthFunc = ztst[dssel.ztst];
|
|
}
|
|
|
|
m_om_dss[dssel] = dss;
|
|
|
|
i = m_om_dss.find(dssel);
|
|
}
|
|
|
|
dev->OMSetDepthStencilState(i->second);
|
|
|
|
hash_map<uint32, Direct3DBlendState9*>::const_iterator j = m_om_bs.find(bsel);
|
|
|
|
if(j == m_om_bs.end())
|
|
{
|
|
Direct3DBlendState9* bs = new Direct3DBlendState9();
|
|
|
|
memset(bs, 0, sizeof(*bs));
|
|
|
|
bs->BlendEnable = bsel.abe;
|
|
|
|
if(bsel.abe)
|
|
{
|
|
// (A:Cs/Cd/0 - B:Cs/Cd/0) * C:As/Ad/FIX + D:Cs/Cd/0
|
|
|
|
static const struct {int bogus; D3DBLENDOP op; D3DBLEND src, dst;} map[3*3*3*3] =
|
|
{
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ONE, D3DBLEND_ZERO}, // 0000: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cs ==> Cs
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ONE}, // 0001: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cd ==> Cd
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ZERO}, // 0002: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + 0 ==> 0
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ONE, D3DBLEND_ZERO}, // 0010: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cs ==> Cs
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ONE}, // 0011: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cd ==> Cd
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ZERO}, // 0012: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + 0 ==> 0
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ONE, D3DBLEND_ZERO}, // 0020: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cs ==> Cs
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ONE}, // 0021: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cd ==> Cd
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ZERO}, // 0022: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + 0 ==> 0
|
|
{1, D3DBLENDOP_SUBTRACT, D3DBLEND_SRCALPHA, D3DBLEND_SRCALPHA}, // * 0100: (Cs - Cd)*As + Cs ==> Cs*(As + 1) - Cd*As
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA}, // 0101: (Cs - Cd)*As + Cd ==> Cs*As + Cd*(1 - As)
|
|
{0, D3DBLENDOP_SUBTRACT, D3DBLEND_SRCALPHA, D3DBLEND_SRCALPHA}, // 0102: (Cs - Cd)*As + 0 ==> Cs*As - Cd*As
|
|
{1, D3DBLENDOP_SUBTRACT, D3DBLEND_DESTALPHA, D3DBLEND_DESTALPHA}, // * 0110: (Cs - Cd)*Ad + Cs ==> Cs*(Ad + 1) - Cd*Ad
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_DESTALPHA, D3DBLEND_INVDESTALPHA}, // 0111: (Cs - Cd)*Ad + Cd ==> Cs*Ad + Cd*(1 - Ad)
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_DESTALPHA, D3DBLEND_DESTALPHA}, // 0112: (Cs - Cd)*Ad + 0 ==> Cs*Ad - Cd*Ad
|
|
{1, D3DBLENDOP_SUBTRACT, D3DBLEND_BLENDFACTOR, D3DBLEND_BLENDFACTOR}, // * 0120: (Cs - Cd)*F + Cs ==> Cs*(F + 1) - Cd*F
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_BLENDFACTOR, D3DBLEND_INVBLENDFACTOR}, // 0121: (Cs - Cd)*F + Cd ==> Cs*F + Cd*(1 - F)
|
|
{0, D3DBLENDOP_SUBTRACT, D3DBLEND_BLENDFACTOR, D3DBLEND_BLENDFACTOR}, // 0122: (Cs - Cd)*F + 0 ==> Cs*F - Cd*F
|
|
{1, D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_ZERO}, // * 0200: (Cs - 0)*As + Cs ==> Cs*(As + 1)
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_ONE}, // 0201: (Cs - 0)*As + Cd ==> Cs*As + Cd
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_ZERO}, // 0202: (Cs - 0)*As + 0 ==> Cs*As
|
|
{1, D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_ZERO}, // * 0210: (Cs - 0)*Ad + Cs ==> Cs*(As + 1)
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_DESTALPHA, D3DBLEND_ONE}, // 0211: (Cs - 0)*Ad + Cd ==> Cs*Ad + Cd
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_DESTALPHA, D3DBLEND_ZERO}, // 0212: (Cs - 0)*Ad + 0 ==> Cs*Ad
|
|
{1, D3DBLENDOP_ADD, D3DBLEND_BLENDFACTOR, D3DBLEND_ZERO}, // * 0220: (Cs - 0)*F + Cs ==> Cs*(F + 1)
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_BLENDFACTOR, D3DBLEND_ONE}, // 0221: (Cs - 0)*F + Cd ==> Cs*F + Cd
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_BLENDFACTOR, D3DBLEND_ZERO}, // 0222: (Cs - 0)*F + 0 ==> Cs*F
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_INVSRCALPHA, D3DBLEND_SRCALPHA}, // 1000: (Cd - Cs)*As + Cs ==> Cd*As + Cs*(1 - As)
|
|
{1, D3DBLENDOP_REVSUBTRACT, D3DBLEND_SRCALPHA, D3DBLEND_SRCALPHA}, // * 1001: (Cd - Cs)*As + Cd ==> Cd*(As + 1) - Cs*As
|
|
{0, D3DBLENDOP_REVSUBTRACT, D3DBLEND_SRCALPHA, D3DBLEND_SRCALPHA}, // 1002: (Cd - Cs)*As + 0 ==> Cd*As - Cs*As
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_INVDESTALPHA, D3DBLEND_DESTALPHA}, // 1010: (Cd - Cs)*Ad + Cs ==> Cd*Ad + Cs*(1 - Ad)
|
|
{1, D3DBLENDOP_REVSUBTRACT, D3DBLEND_DESTALPHA, D3DBLEND_DESTALPHA}, // * 1011: (Cd - Cs)*Ad + Cd ==> Cd*(Ad + 1) - Cs*Ad
|
|
{0, D3DBLENDOP_REVSUBTRACT, D3DBLEND_DESTALPHA, D3DBLEND_DESTALPHA}, // 1012: (Cd - Cs)*Ad + 0 ==> Cd*Ad - Cs*Ad
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_INVBLENDFACTOR, D3DBLEND_BLENDFACTOR}, // 1020: (Cd - Cs)*F + Cs ==> Cd*F + Cs*(1 - F)
|
|
{1, D3DBLENDOP_REVSUBTRACT, D3DBLEND_BLENDFACTOR, D3DBLEND_BLENDFACTOR},// * 1021: (Cd - Cs)*F + Cd ==> Cd*(F + 1) - Cs*F
|
|
{0, D3DBLENDOP_REVSUBTRACT, D3DBLEND_BLENDFACTOR, D3DBLEND_BLENDFACTOR},// 1022: (Cd - Cs)*F + 0 ==> Cd*F - Cs*F
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ONE, D3DBLEND_ZERO}, // 1100: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cs ==> Cs
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ONE}, // 1101: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cd ==> Cd
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ZERO}, // 1102: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + 0 ==> 0
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ONE, D3DBLEND_ZERO}, // 1110: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cs ==> Cs
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ONE}, // 1111: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cd ==> Cd
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ZERO}, // 1112: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + 0 ==> 0
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ONE, D3DBLEND_ZERO}, // 1120: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cs ==> Cs
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ONE}, // 1121: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cd ==> Cd
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ZERO}, // 1122: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + 0 ==> 0
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ONE, D3DBLEND_SRCALPHA}, // 1200: (Cd - 0)*As + Cs ==> Cs + Cd*As
|
|
{2, D3DBLENDOP_ADD, D3DBLEND_DESTCOLOR, D3DBLEND_SRCALPHA}, // ** 1201: (Cd - 0)*As + Cd ==> Cd*(1 + As) // ffxii main menu background glow effect
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_SRCALPHA}, // 1202: (Cd - 0)*As + 0 ==> Cd*As
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ONE, D3DBLEND_DESTALPHA}, // 1210: (Cd - 0)*Ad + Cs ==> Cs + Cd*Ad
|
|
{2, D3DBLENDOP_ADD, D3DBLEND_DESTCOLOR, D3DBLEND_DESTALPHA}, // ** 1211: (Cd - 0)*Ad + Cd ==> Cd*(1 + Ad)
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_DESTALPHA}, // 1212: (Cd - 0)*Ad + 0 ==> Cd*Ad
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ONE, D3DBLEND_BLENDFACTOR}, // 1220: (Cd - 0)*F + Cs ==> Cs + Cd*F
|
|
{2, D3DBLENDOP_ADD, D3DBLEND_DESTCOLOR, D3DBLEND_BLENDFACTOR}, // ** 1221: (Cd - 0)*F + Cd ==> Cd*(1 + F)
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_BLENDFACTOR}, // 1222: (Cd - 0)*F + 0 ==> Cd*F
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_INVSRCALPHA, D3DBLEND_ZERO}, // 2000: (0 - Cs)*As + Cs ==> Cs*(1 - As)
|
|
{0, D3DBLENDOP_REVSUBTRACT, D3DBLEND_SRCALPHA, D3DBLEND_ONE}, // 2001: (0 - Cs)*As + Cd ==> Cd - Cs*As
|
|
{0, D3DBLENDOP_REVSUBTRACT, D3DBLEND_SRCALPHA, D3DBLEND_ZERO}, // 2002: (0 - Cs)*As + 0 ==> 0 - Cs*As
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_INVDESTALPHA, D3DBLEND_ZERO}, // 2010: (0 - Cs)*Ad + Cs ==> Cs*(1 - Ad)
|
|
{0, D3DBLENDOP_REVSUBTRACT, D3DBLEND_DESTALPHA, D3DBLEND_ONE}, // 2011: (0 - Cs)*Ad + Cd ==> Cd - Cs*Ad
|
|
{0, D3DBLENDOP_REVSUBTRACT, D3DBLEND_DESTALPHA, D3DBLEND_ZERO}, // 2012: (0 - Cs)*Ad + 0 ==> 0 - Cs*Ad
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_INVBLENDFACTOR, D3DBLEND_ZERO}, // 2020: (0 - Cs)*F + Cs ==> Cs*(1 - F)
|
|
{0, D3DBLENDOP_REVSUBTRACT, D3DBLEND_BLENDFACTOR, D3DBLEND_ONE}, // 2021: (0 - Cs)*F + Cd ==> Cd - Cs*F
|
|
{0, D3DBLENDOP_REVSUBTRACT, D3DBLEND_BLENDFACTOR, D3DBLEND_ZERO}, // 2022: (0 - Cs)*F + 0 ==> 0 - Cs*F
|
|
{0, D3DBLENDOP_SUBTRACT, D3DBLEND_ONE, D3DBLEND_SRCALPHA}, // 2100: (0 - Cd)*As + Cs ==> Cs - Cd*As
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_INVSRCALPHA}, // 2101: (0 - Cd)*As + Cd ==> Cd*(1 - As)
|
|
{0, D3DBLENDOP_SUBTRACT, D3DBLEND_ZERO, D3DBLEND_SRCALPHA}, // 2102: (0 - Cd)*As + 0 ==> 0 - Cd*As
|
|
{0, D3DBLENDOP_SUBTRACT, D3DBLEND_ONE, D3DBLEND_DESTALPHA}, // 2110: (0 - Cd)*Ad + Cs ==> Cs - Cd*Ad
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_INVDESTALPHA}, // 2111: (0 - Cd)*Ad + Cd ==> Cd*(1 - Ad)
|
|
{0, D3DBLENDOP_SUBTRACT, D3DBLEND_ONE, D3DBLEND_DESTALPHA}, // 2112: (0 - Cd)*Ad + 0 ==> 0 - Cd*Ad
|
|
{0, D3DBLENDOP_SUBTRACT, D3DBLEND_ONE, D3DBLEND_BLENDFACTOR}, // 2120: (0 - Cd)*F + Cs ==> Cs - Cd*F
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_INVBLENDFACTOR}, // 2121: (0 - Cd)*F + Cd ==> Cd*(1 - F)
|
|
{0, D3DBLENDOP_SUBTRACT, D3DBLEND_ONE, D3DBLEND_BLENDFACTOR}, // 2122: (0 - Cd)*F + 0 ==> 0 - Cd*F
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ONE, D3DBLEND_ZERO}, // 2200: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cs ==> Cs
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ONE}, // 2201: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cd ==> Cd
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ZERO}, // 2202: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + 0 ==> 0
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ONE, D3DBLEND_ZERO}, // 2210: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cs ==> Cs
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ONE}, // 2211: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cd ==> Cd
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ZERO}, // 2212: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + 0 ==> 0
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ONE, D3DBLEND_ZERO}, // 2220: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cs ==> Cs
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ONE}, // 2221: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cd ==> Cd
|
|
{0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ZERO}, // 2222: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + 0 ==> 0
|
|
};
|
|
|
|
// bogus: 0100, 0110, 0120, 0200, 0210, 0220, 1001, 1011, 1021
|
|
|
|
// tricky: 1201, 1211, 1221
|
|
//
|
|
// Source.rgb = float3(1, 1, 1);
|
|
// 1201 Cd*(1 + As) => Source * Dest color + Dest * Source alpha
|
|
// 1211 Cd*(1 + Ad) => Source * Dest color + Dest * Dest alpha
|
|
// 1221 Cd*(1 + F) => Source * Dest color + Dest * Factor
|
|
|
|
int i = ((bsel.a * 3 + bsel.b) * 3 + bsel.c) * 3 + bsel.d;
|
|
|
|
bs->BlendOp = map[i].op;
|
|
bs->SrcBlend = map[i].src;
|
|
bs->DestBlend = map[i].dst;
|
|
bs->BlendOpAlpha = D3DBLENDOP_ADD;
|
|
bs->SrcBlendAlpha = D3DBLEND_ONE;
|
|
bs->DestBlendAlpha = D3DBLEND_ZERO;
|
|
|
|
if(map[i].bogus == 1)
|
|
{
|
|
ASSERT(0);
|
|
|
|
(bsel.a == 0 ? bs->SrcBlend : bs->DestBlend) = D3DBLEND_ONE;
|
|
}
|
|
}
|
|
|
|
if(bsel.wr) bs->RenderTargetWriteMask |= D3DCOLORWRITEENABLE_RED;
|
|
if(bsel.wg) bs->RenderTargetWriteMask |= D3DCOLORWRITEENABLE_GREEN;
|
|
if(bsel.wb) bs->RenderTargetWriteMask |= D3DCOLORWRITEENABLE_BLUE;
|
|
if(bsel.wa) bs->RenderTargetWriteMask |= D3DCOLORWRITEENABLE_ALPHA;
|
|
|
|
m_om_bs[bsel] = bs;
|
|
|
|
j = m_om_bs.find(bsel);
|
|
}
|
|
|
|
dev->OMSetBlendState(j->second, afix >= 0x80 ? 0xffffff : 0x020202 * afix);
|
|
}
|