naomi2: use TA parser. Use N2light directly with vk, dx11

Use TA parser to handle list type and clipping for Naomi 2 polys.
Pass all pass-throuch TA data to TA parser but stop on naomi2 command.
Set default projection matrix instead of identity (fixes Area conquered
screen invisible in initd).
Change N2Light and N2LightModel so they are usable in GLSL (vulkan) and
HLSL (dx11).
TA parser throws exception for unhandled param.
ta_vtx.cpp refactoring.
Support for subtractive lights (diffuse+specular). Used in some clubk
circuits.
Fix vulkan crash when direct FB render.
This commit is contained in:
Flyinghead 2022-03-16 17:28:45 +01:00
parent 5b3d36e081
commit 56768f2d3d
19 changed files with 789 additions and 955 deletions

View File

@ -458,10 +458,13 @@ void Emulator::loadGame(const char *path, LoadProgress *progress)
mem_map_default();
config::Settings::instance().reset();
dc_reset(true);
config::Settings::instance().load(false);
dc_reset(true);
memset(&settings.network.md5, 0, sizeof(settings.network.md5));
if (settings.platform.isNaomi2() && config::RendererType == RenderType::DirectX9)
throw FlycastException("DirectX 9 doesn't support Naomi 2 games. Select a different graphics API");
if (settings.platform.isConsole())
{
if (settings.content.path.empty())

View File

@ -270,11 +270,9 @@ struct State
{
static constexpr u32 Null = 0xffffffff;
int listType = -1;
u32 gmp = Null;
u32 instance = Null;
u32 projMatrix = Null;
u32 tileclip = 0;
u32 lightModel = Null;
u32 lights[MAX_LIGHTS] = {
Null, Null, Null, Null, Null, Null, Null, Null,
@ -286,11 +284,9 @@ struct State
void reset()
{
listType = -1;
gmp = Null;
instance = Null;
projMatrix = Null;
tileclip = 0;
lightModel = Null;
for (auto& light : lights)
light = Null;
@ -470,21 +466,6 @@ struct State
elan::curLights[lightId] = plight;
}
void setClipMode(PCW pcw)
{
tileclip = (tileclip & ~0xF0000000) | (pcw.userClip << 28);
}
void setClipTiles(u32 xmin, u32 ymin, u32 xmax, u32 ymax)
{
u32 t = tileclip & 0xF0000000;
t |= xmin & 0x3f; // 6 bits
t |= (xmax & 0x3f) << 6; // 6 bits
t |= (ymin & 0x1f) << 12; // 5 bits
t |= (ymax & 0x1f) << 17; // 5 bits
tileclip = t;
}
void update()
{
updateMatrix();
@ -505,11 +486,11 @@ struct State
void serialize(Serializer& ser)
{
ser << listType;
ser << ta_get_list_type();
ser << gmp;
ser << instance;
ser << projMatrix;
ser << tileclip;
ser << ta_get_tileclip();
ser << lightModel;
ser << lights;
}
@ -521,11 +502,15 @@ struct State
reset();
return;
}
u32 listType;
deser >> listType;
ta_set_list_type(listType);
deser >> gmp;
deser >> instance;
deser >> projMatrix;
u32 tileclip;
deser >> tileclip;
ta_set_tileclip(tileclip);
deser >> lightModel;
deser >> lights;
update();
@ -592,12 +577,18 @@ static void setNormal(Vertex& vd, const T& vs)
vd.nz = normal.z;
}
static void addModelColors(glm::vec4& baseCol0, glm::vec4& offsetCol0, glm::vec4& baseCol1, glm::vec4& offsetCol1)
static void setModelColors(glm::vec4& baseCol0, glm::vec4& offsetCol0, glm::vec4& baseCol1, glm::vec4& offsetCol1)
{
baseCol0 += gmpDiffuseColor0;
offsetCol0 += gmpSpecularColor0;
baseCol1 += gmpDiffuseColor1;
offsetCol1 += gmpSpecularColor1;
if (curGmp == nullptr)
return;
if (curGmp->paramSelect.d0)
baseCol0 = gmpDiffuseColor0;
if (curGmp->paramSelect.s0)
offsetCol0 = gmpSpecularColor0;
if (curGmp->paramSelect.d1)
baseCol1 = gmpDiffuseColor1;
if (curGmp->paramSelect.s1)
offsetCol1 = gmpSpecularColor1;
}
template <typename T>
@ -609,11 +600,11 @@ void convertVertex(const N2_VERTEX& vs, Vertex& vd)
setCoords(vd, vs.x, vs.y, vs.z);
setNormal(vd, vs);
SetEnvMapUV(vd);
glm::vec4 baseCol0(0);
glm::vec4 baseCol0(1);
glm::vec4 offsetCol0(0);
glm::vec4 baseCol1(0);
glm::vec4 baseCol1(1);
glm::vec4 offsetCol1(0);
addModelColors(baseCol0, offsetCol0, baseCol1, offsetCol1);
setModelColors(baseCol0, offsetCol0, baseCol1, offsetCol1);
*(u32 *)vd.col = packColor(baseCol0);
*(u32 *)vd.spc = packColor(offsetCol0);
@ -631,7 +622,7 @@ void convertVertex(const N2_VERTEX_VR& vs, Vertex& vd)
glm::vec4 offsetCol0(0);
glm::vec4 baseCol1 = unpackColor(vs.rgb.argb1);
glm::vec4 offsetCol1(0);
addModelColors(baseCol0, offsetCol0, baseCol1, offsetCol1);
setModelColors(baseCol0, offsetCol0, baseCol1, offsetCol1);
*(u32 *)vd.col = packColor(baseCol0);
*(u32 *)vd.spc = packColor(offsetCol0);
*(u32 *)vd.col1 = packColor(baseCol1);
@ -644,11 +635,11 @@ void convertVertex(const N2_VERTEX_VU& vs, Vertex& vd)
setCoords(vd, vs.x, vs.y, vs.z);
setNormal(vd, vs);
setUV(vs, vd);
glm::vec4 baseCol0(0);
glm::vec4 baseCol0(1);
glm::vec4 offsetCol0(0);
glm::vec4 baseCol1(0);
glm::vec4 baseCol1(1);
glm::vec4 offsetCol1(0);
addModelColors(baseCol0, offsetCol0, baseCol1, offsetCol1);
setModelColors(baseCol0, offsetCol0, baseCol1, offsetCol1);
*(u32 *)vd.col = packColor(baseCol0);
*(u32 *)vd.spc = packColor(offsetCol0);
*(u32 *)vd.col1 = packColor(baseCol1);
@ -665,7 +656,7 @@ void convertVertex(const N2_VERTEX_VUR& vs, Vertex& vd)
glm::vec4 offsetCol0(0);
glm::vec4 baseCol1 = unpackColor(vs.rgb.argb1);
glm::vec4 offsetCol1(0);
addModelColors(baseCol0, offsetCol0, baseCol1, offsetCol1);
setModelColors(baseCol0, offsetCol0, baseCol1, offsetCol1);
*(u32 *)vd.col = packColor(baseCol0);
*(u32 *)vd.spc = packColor(offsetCol0);
*(u32 *)vd.col1 = packColor(baseCol1);
@ -678,11 +669,11 @@ void convertVertex(const N2_VERTEX_VUB& vs, Vertex& vd)
setCoords(vd, vs.x, vs.y, vs.z);
setNormal(vd, vs);
setUV(vs, vd);
glm::vec4 baseCol0(0);
glm::vec4 baseCol0(1);
glm::vec4 offsetCol0(0);
glm::vec4 baseCol1(0);
glm::vec4 baseCol1(1);
glm::vec4 offsetCol1(0);
addModelColors(baseCol0, offsetCol0, baseCol1, offsetCol1);
setModelColors(baseCol0, offsetCol0, baseCol1, offsetCol1);
*(u32 *)vd.col = packColor(baseCol0);
*(u32 *)vd.col1 = packColor(baseCol1);
// Stuff the bump map normals and parameters in the specular colors
@ -1101,7 +1092,7 @@ static void sendMVPolygon(ICHList *list, const T *vtx, bool needClipping)
mvp.isp.DepthMode &= 3;
mvp.mvMatrix = taMVMatrix;
mvp.projMatrix = taProjMatrix;
ta_add_poly(state.listType, mvp);
ta_add_poly(list->pcw.listType, mvp);
ModifierVolumeClipper clipper(needClipping);
glm::vec3 vtx0{};
@ -1162,11 +1153,11 @@ static void sendLights()
model.lightCount = 0;
if (curLightModel == nullptr)
{
model.useBaseOver = false;
model.useBaseOver = 0;
for (int i = 0; i < 2; i++)
{
model.ambientMaterialBase[i] = false;
model.ambientMaterialOffset[i] = false;
model.ambientMaterialBase[i] = 0;
model.ambientMaterialOffset[i] = 0;
model.ambientBase[i][0] = model.ambientBase[i][1] = model.ambientBase[i][2] = model.ambientBase[i][3] = 1.f;
}
memset(model.ambientOffset, 0, sizeof(model.ambientOffset));
@ -1253,7 +1244,6 @@ static void sendLights()
static void setStateParams(PolyParam& pp, const ICHList *list)
{
sendLights();
pp.tileclip = state.tileclip;
pp.mvMatrix = taMVMatrix;
pp.normalMatrix = taNormalMatrix;
pp.projMatrix = taProjMatrix;
@ -1310,7 +1300,7 @@ static void setStateParams(PolyParam& pp, const ICHList *list)
pp.specularColor[1] = false;
}
// else if (pp.pcw.Volume == 1)
// printf("2-Volume poly listType %d vtxtype %x gmp params %x diff tcw %08x tsp %08x\n", state.listType, list->flags, curGmp->paramSelect.full,
// printf("2-Volume poly listType %d vtxtype %x gmp params %x diff tcw %08x tsp %08x\n", ta_get_list_type(), list->flags, curGmp->paramSelect.full,
// pp.tcw.full ^ pp.tcw1.full, pp.tsp.full ^ pp.tsp1.full);
}
@ -1325,7 +1315,10 @@ static void sendPolygon(ICHList *list)
N2_VERTEX *vtx = (N2_VERTEX *)((u8 *)list + sizeof(ICHList));
if (!isBetweenNearAndFar(vtx, list->vtxCount, needClipping))
break;
if (state.listType & 1)
int listType = ta_get_list_type();
if (listType == -1)
listType = list->pcw.listType;
if (listType & 1)
sendMVPolygon(list, vtx, needClipping);
else
{
@ -1339,7 +1332,7 @@ static void sendPolygon(ICHList *list)
pp.tsp = list->tsp0;
pp.tsp1 = list->tsp1;
setStateParams(pp, list);
ta_add_poly(state.listType, pp);
ta_add_poly(pp);
sendVertices(list, vtx, needClipping);
}
@ -1351,7 +1344,10 @@ static void sendPolygon(ICHList *list)
N2_VERTEX_VU *vtx = (N2_VERTEX_VU *)((u8 *)list + sizeof(ICHList));
if (!isBetweenNearAndFar(vtx, list->vtxCount, needClipping))
break;
if (state.listType & 1)
int listType = ta_get_list_type();
if (listType == -1)
listType = list->pcw.listType;
if (listType & 1)
sendMVPolygon(list, vtx, needClipping);
else
{
@ -1367,7 +1363,7 @@ static void sendPolygon(ICHList *list)
pp.tsp1 = list->tsp1;
pp.tcw1 = list->tcw1;
setStateParams(pp, list);
ta_add_poly(state.listType, pp);
ta_add_poly(pp);
sendVertices(list, vtx, needClipping);
}
@ -1391,7 +1387,7 @@ static void sendPolygon(ICHList *list)
pp.tsp1 = list->tsp1;
pp.tcw1 = list->tcw1;
setStateParams(pp, list);
ta_add_poly(state.listType, pp);
ta_add_poly(pp);
sendVertices(list, vtx, needClipping);
}
@ -1412,7 +1408,7 @@ static void sendPolygon(ICHList *list)
pp.tsp = list->tsp0;
pp.tsp1 = list->tsp1;
setStateParams(pp, list);
ta_add_poly(state.listType, pp);
ta_add_poly(pp);
sendVertices(list, vtx, needClipping);
}
@ -1437,7 +1433,7 @@ static void sendPolygon(ICHList *list)
pp.tsp1 = list->tsp1;
pp.tcw1 = list->tcw1;
setStateParams(pp, list);
ta_add_poly(state.listType, pp);
ta_add_poly(pp);
sendVertices(list, vtx, needClipping);
}
@ -1526,7 +1522,7 @@ static void executeCommand(u8 *data, int size)
if (Active)
{
cullingReversed = model->param.cwCulling == 0;
state.setClipMode(model->pcw);
ta_set_tileclip((model->pcw.userClip << 28) | (ta_get_tileclip() & 0x0fffffff));
openModifierVolume = model->param.openVolume;
shadowedVolume = model->pcw.shadow;
modelTSP = model->tsp;
@ -1591,20 +1587,20 @@ static void executeCommand(u8 *data, int size)
if (link->offset & 0x80000000)
{
// elan v10 only
DEBUG_LOG(PVR, "Texture DMA from %x to %x (%x)", DMAC_SAR(2), link->_res & 0x1ffffff8, link->size);
memcpy(&vram[link->_res & VRAM_MASK], &mem_b[DMAC_SAR(2) & RAM_MASK], link->size);
DEBUG_LOG(PVR, "Texture DMA from %x to %x (%x)", DMAC_SAR(2), link->vramAddress & 0x1ffffff8, link->size);
memcpy(&vram[link->vramAddress & VRAM_MASK], &mem_b[DMAC_SAR(2) & RAM_MASK], link->size);
reg74 |= 1;
}
else if (link->offset & 0x20000000)
{
// elan v10 only
DEBUG_LOG(PVR, "Texture DMA from eram %x -> %x (%x)", link->offset & 0x01fffff8, link->_res & VRAM_MASK, link->size);
memcpy(&vram[link->_res & VRAM_MASK], &RAM[link->offset & ELAN_RAM_MASK], link->size);
DEBUG_LOG(PVR, "Texture DMA from eram %x -> %x (%x)", link->offset & ELAN_RAM_MASK, link->vramAddress & VRAM_MASK, link->size);
memcpy(&vram[link->vramAddress & VRAM_MASK], &RAM[link->offset & ELAN_RAM_MASK], link->size);
reg74 |= 1;
}
else
{
DEBUG_LOG(PVR, "Link to %x (%x)", link->offset & 0x1ffffff8, link->size);
DEBUG_LOG(PVR, "Link to %8x (%x)", link->offset, link->size);
executeCommand<Active>(&RAM[link->offset & ELAN_RAM_MASK], link->size);
}
size -= sizeof(Link);
@ -1630,69 +1626,84 @@ static void executeCommand(u8 *data, int size)
break;
default:
DEBUG_LOG(PVR, "Unhandled Elan command %x", cmd->pcw.n2Command);
WARN_LOG(PVR, "Unhandled Elan command %x", cmd->pcw.n2Command);
size -= 32;
break;
}
}
else
{
u32 pcw = *(u32 *)data;
if ((pcw & 0xd0ffff00) == 0x808c0000) // display list
if (Active)
{
if (Active)
{
DEBUG_LOG(PVR, "Display list type %d", (pcw >> 24) & 0xf);
state.reset();
state.listType = (pcw >> 24) & 0xf;
// TODO is this the right place for this?
SQBuffer eol{};
ta_vtx_data32(&eol);
u32 pcw = *(u32 *)data;
DEBUG_LOG(PVR, "Geometry type %d - %08x", (pcw >> 24) & 0xf, pcw);
try {
size -= ta_add_ta_data((u32 *)data, size);
} catch (const TAParserException& e) {
size = 0;
}
size -= 24 * 4;
}
else if ((pcw & 0xd0fcff00) == 0x80800000) // User clipping
{
if (Active)
{
state.setClipMode((PCW&)pcw);
DEBUG_LOG(PVR, "User clip type %d", ((PCW&)pcw).userClip);
}
size -= 0xE0;
}
else if ((pcw & 0xd0ffff00) == 0x80000000) // geometry follows or linked?
{
if (Active)
{
DEBUG_LOG(PVR, "Geometry type %d - %08x", (pcw >> 24) & 0xf, pcw);
state.listType = (pcw >> 24) & 0xf;
size -= 32;
ta_add_ta_data(state.listType, (u32 *)(data + 32), size - 32);
}
size = 32;
}
else if (pcw == 0x20000000)
{
// User clipping
if (Active)
{
u32 *tiles = (u32 *)data + 4;
DEBUG_LOG(PVR, "User clipping %d,%d - %d,%d", tiles[0] * 32, tiles[1] * 32,
tiles[2] * 32, tiles[3] * 32);
state.setClipTiles(tiles[0], tiles[1], tiles[2], tiles[3]);
}
size -= 32;
}
else
{
if (Active)
u32 vertexSize = 32;
int listType = ta_get_list_type();
int i = 0;
while (i < size)
{
if (pcw != 0)
INFO_LOG(PVR, "Unhandled command %x", pcw);
for (int i = 0; i < 32; i += 4)
DEBUG_LOG(PVR, " %08x: %08x", (u32)(&data[i] - RAM), *(u32 *)&data[i]);
PCW pcw = *(PCW *)&data[i];
if (pcw.naomi2 == 1)
break;
switch (pcw.paraType)
{
case ParamType_End_Of_List:
listType = -1;
i += 32;
break;
case ParamType_Object_List_Set:
case ParamType_User_Tile_Clip:
i += 32;
break;
case ParamType_Polygon_or_Modifier_Volume:
{
static const u32 * const PolyTypeLut = TaTypeLut::instance().table;
if (listType == -1)
listType = pcw.listType;
if (listType & 1)
{
// modifier volumes
vertexSize = 64;
i += 32;
}
else
{
u32 polyId = PolyTypeLut[pcw.objectControl];
u32 polySize = polyId >> 30;
u32 vertexType = (u8)polyId;
if (vertexType == 5 || vertexType == 6 || (vertexType >= 11 && vertexType <= 14))
vertexSize = 64;
else
vertexSize = 32;
i += polySize == SZ64 ? 64 : 32;
}
}
break;
case ParamType_Sprite:
if (listType == -1)
listType = pcw.listType;
vertexSize = 64;
i += 32;
break;
case ParamType_Vertex_Parameter:
i += vertexSize;
break;
default:
WARN_LOG(PVR, "Invalid param type %d", pcw.paraType);
i = size;
break;
}
}
size -= 32;
size -= i;
}
}
data += oldSize - size;

View File

@ -65,6 +65,7 @@ union PCW
u32 endOfStrip : 1;
u32 paraType : 3;
};
u8 objectControl;
u32 full;
};
@ -382,7 +383,7 @@ struct Link : public ElanBase
{
// 08000f00
u32 offset;
u32 _res; // 09000000
u32 vramAddress; // for texture DMA xfers, otherwise 09000000
u32 size;
u32 _res0[4];
};

View File

@ -45,6 +45,7 @@ void reset(bool hard)
rend_reset();
tactx_Term();
elan::reset(hard);
ta_parse_reset();
}
void init()

View File

@ -263,6 +263,203 @@ static NOINLINE void DYNACALL ta_handle_cmd(u32 trans)
static OnLoad ol_fillfsm(&fill_fsm);
/*
Volume,Col_Type,Texture,Offset,Gouraud,16bit_UV
0 0 0 (0) x invalid Polygon Type 0 Polygon Type 0
0 0 1 x x 0 Polygon Type 0 Polygon Type 3
0 0 1 x x 1 Polygon Type 0 Polygon Type 4
0 1 0 (0) x invalid Polygon Type 0 Polygon Type 1
0 1 1 x x 0 Polygon Type 0 Polygon Type 5
0 1 1 x x 1 Polygon Type 0 Polygon Type 6
0 2 0 (0) x invalid Polygon Type 1 Polygon Type 2
0 2 1 0 x 0 Polygon Type 1 Polygon Type 7
0 2 1 0 x 1 Polygon Type 1 Polygon Type 8
0 2 1 1 x 0 Polygon Type 2 Polygon Type 7
0 2 1 1 x 1 Polygon Type 2 Polygon Type 8
0 3 0 (0) x invalid Polygon Type 0 Polygon Type 2
0 3 1 x x 0 Polygon Type 0 Polygon Type 7
0 3 1 x x 1 Polygon Type 0 Polygon Type 8
1 0 0 (0) x invalid Polygon Type 3 Polygon Type 9
1 0 1 x x 0 Polygon Type 3 Polygon Type 11
1 0 1 x x 1 Polygon Type 3 Polygon Type 12
1 2 0 (0) x invalid Polygon Type 4 Polygon Type 10
1 2 1 x x 0 Polygon Type 4 Polygon Type 13
1 2 1 x x 1 Polygon Type 4 Polygon Type 14
1 3 0 (0) x invalid Polygon Type 3 Polygon Type 10
1 3 1 x x 0 Polygon Type 3 Polygon Type 13
1 3 1 x x 1 Polygon Type 3 Polygon Type 14
Sprites :
(0) (0) 0 (0) (0) invalid Sprite Sprite Type 0
(0) (0) 1 x (0) (1) Sprite Sprite Type 1
*/
//helpers 0-14
u32 TaTypeLut::poly_data_type_id(PCW pcw)
{
if (pcw.Texture)
{
//textured
if (pcw.Volume==0)
{ //single volume
if (pcw.Col_Type==0)
{
if (pcw.UV_16bit==0)
return 3; //(Textured, Packed Color , 32b uv)
else
return 4; //(Textured, Packed Color , 16b uv)
}
else if (pcw.Col_Type==1)
{
if (pcw.UV_16bit==0)
return 5; //(Textured, Floating Color , 32b uv)
else
return 6; //(Textured, Floating Color , 16b uv)
}
else
{
if (pcw.UV_16bit==0)
return 7; //(Textured, Intensity , 32b uv)
else
return 8; //(Textured, Intensity , 16b uv)
}
}
else
{
//two volumes
if (pcw.Col_Type==0)
{
if (pcw.UV_16bit==0)
return 11; //(Textured, Packed Color, with Two Volumes)
else
return 12; //(Textured, Packed Color, 16bit UV, with Two Volumes)
}
else if (pcw.Col_Type==1)
{
//die ("invalid");
return 0xFFFFFFFF;
}
else
{
if (pcw.UV_16bit==0)
return 13; //(Textured, Intensity, with Two Volumes)
else
return 14; //(Textured, Intensity, 16bit UV, with Two Volumes)
}
}
}
else
{
//non textured
if (pcw.Volume==0)
{ //single volume
if (pcw.Col_Type==0)
return 0; //(Non-Textured, Packed Color)
else if (pcw.Col_Type==1)
return 1; //(Non-Textured, Floating Color)
else
return 2; //(Non-Textured, Intensity)
}
else
{
//two volumes
if (pcw.Col_Type==0)
return 9; //(Non-Textured, Packed Color, with Two Volumes)
else if (pcw.Col_Type==1)
{
//die ("invalid");
return 0xFFFFFFFF;
}
else
{
return 10; //(Non-Textured, Intensity, with Two Volumes)
}
}
}
}
//0-4 | 0x80
u32 TaTypeLut::poly_header_type_size(PCW pcw)
{
if (pcw.Volume == 0)
{
if ( pcw.Col_Type<2 ) //0,1
{
return 0 | 0; //Polygon Type 0 -- SZ32
}
else if ( pcw.Col_Type == 2 )
{
if (pcw.Texture)
{
if (pcw.Offset)
{
return 2 | 0x80; //Polygon Type 2 -- SZ64
}
else
{
return 1 | 0; //Polygon Type 1 -- SZ32
}
}
else
{
return 1 | 0; //Polygon Type 1 -- SZ32
}
}
else //col_type ==3
{
return 0 | 0; //Polygon Type 0 -- SZ32
}
}
else
{
if ( pcw.Col_Type==0 ) //0
{
return 3 | 0; //Polygon Type 3 -- SZ32
}
else if ( pcw.Col_Type==2 ) //2
{
return 4 | 0x80; //Polygon Type 4 -- SZ64
}
else if ( pcw.Col_Type==3 ) //3
{
return 3 | 0; //Polygon Type 3 -- SZ32
}
else
{
return 0xFFDDEEAA;//die ("data->pcw.Col_Type==1 && volume ==1");
}
}
}
TaTypeLut::TaTypeLut()
{
for (int i = 0; i < 256; i++)
{
PCW pcw;
pcw.obj_ctrl = i;
u32 rv = poly_data_type_id(pcw);
u32 type = poly_header_type_size(pcw);
if (type & 0x80)
rv |= SZ64 << 30;
else
rv |= SZ32 << 30;
rv |= (type & 0x7F) << 8;
table[i] = rv;
}
}
static u32 opbSize(int n)
{
return n == 0 ? 0 : 16 << n;
@ -305,10 +502,13 @@ void ta_vtx_ListInit()
ta_cur_state = TAS_NS;
ta_fsm_cl = 7;
if (settings.platform.isNaomi2())
ta_parse_reset();
}
void ta_vtx_SoftReset()
{
ta_cur_state=TAS_NS;
ta_cur_state = TAS_NS;
}
static INLINE

View File

@ -3,6 +3,9 @@
#include "ta_ctx.h"
#include "hw/sh4/sh4_if.h"
constexpr u32 SZ32 = 1;
constexpr u32 SZ64 = 2;
struct TA_context;
void ta_vtx_ListInit();
@ -25,4 +28,6 @@ public:
private:
TaTypeLut();
u32 poly_data_type_id(PCW pcw);
u32 poly_header_type_size(PCW pcw);
};

View File

@ -195,30 +195,34 @@ struct N2Light
float color[4];
float direction[4]; // For parallel/spot
float position[4]; // For spot/point
int parallel;
int diffuse[2];
int specular[2];
int routing;
int dmode;
int smode;
int distAttnMode; // For spot/point
int diffuse[2];
int specular[2];
float attnDistA;
float attnDistB;
float attnAngleA; // For spot
float attnAngleB;
int distAttnMode; // For spot/point
int _pad[3];
};
struct N2LightModel
{
N2Light lights[16];
int lightCount;
float ambientBase[2][4]; // base ambient colors
float ambientOffset[2][4]; // offset ambient colors
bool ambientMaterialBase[2]; // base ambient light is multiplied by model material/color
bool ambientMaterialOffset[2]; // offset ambient light is multiplied by model material/color
bool useBaseOver; // base color overflows into offset color
int ambientMaterialBase[2]; // base ambient light is multiplied by model material/color
int ambientMaterialOffset[2];// offset ambient light is multiplied by model material/color
int lightCount;
int useBaseOver; // base color overflows into offset color
int bumpId1; // Light index for vol0 bump mapping
int bumpId2; // Light index for vol1 bump mapping
};
@ -391,11 +395,22 @@ bool rend_framePending();
void SerializeTAContext(Serializer& ser);
void DeserializeTAContext(Deserializer& deser);
void ta_add_poly(int type, const PolyParam& pp);
void ta_add_poly(int type, const ModifierVolumeParam& mvp);
void ta_add_poly(const PolyParam& pp);
void ta_add_poly(int listType, const ModifierVolumeParam& mvp);
void ta_add_vertex(const Vertex& vtx);
void ta_add_triangle(const ModTriangle& tri);
float* ta_add_matrix(const float *matrix);
N2LightModel *ta_add_light(const N2LightModel& light);
void ta_add_ta_data(int listType, u32 *data, u32 size);
u32 ta_add_ta_data(u32 *data, u32 size);
int getTAContextAddresses(u32 *addresses);
u32 ta_get_tileclip();
void ta_set_tileclip(u32 tileclip);
u32 ta_get_list_type();
void ta_set_list_type(u32 listType);
void ta_parse_reset();
class TAParserException : public FlycastException
{
public:
TAParserException() : FlycastException("") {}
};

File diff suppressed because it is too large Load Diff

View File

@ -171,31 +171,26 @@ const char * const DX11N2ColorShader = R"(
#define LMODE_THIN_SURFACE 4
#define LMODE_BUMP_MAP 5
#define ROUTING_BASEDIFF_BASESPEC_ADD 0
#define ROUTING_BASEDIFF_OFFSSPEC_ADD 1
#define ROUTING_OFFSDIFF_BASESPEC_ADD 2
#define ROUTING_OFFSDIFF_OFFSSPEC_ADD 3
#define ROUTING_ALPHADIFF_ADD 4
#define ROUTING_ALPHAATTEN_ADD 5
#define ROUTING_FOGDIFF_ADD 6
#define ROUTING_FOGATTENUATION_ADD 7
#define ROUTING_BASEDIFF_BASESPEC_SUB 8
#define ROUTING_BASEDIFF_OFFSSPEC_SUB 9
#define ROUTING_OFFSDIFF_BASESPEC_SUB 10
#define ROUTING_OFFSDIFF_OFFSSPEC_SUB 11
#define ROUTING_ALPHADIFF_SUB 12
#define ROUTING_ALPHAATTEN_SUB 13
#define ROUTING_SPEC_TO_OFFSET 1
#define ROUTING_DIFF_TO_OFFSET 2
#define ROUTING_ATTENUATION 1 // not handled
#define ROUTING_FOG 2 // not handled
#define ROUTING_ALPHA 4
#define ROUTING_SUB 8
struct N2Light
{
float4 color;
float4 direction;
float4 position;
int parallel;
int routing;
int dmode;
int smode;
int4 diffuse_specular; // diffuse0, diffuse1, specular0, specular1
float attnDistA;
float attnDistB;
float attnAngleA;
@ -207,10 +202,12 @@ struct N2Light
cbuffer lightConstants : register(b2)
{
N2Light lights[16];
int lightCount;
float4 ambientBase[2];
float4 ambientOffset[2];
int4 ambientMaterial; // base0, base1, offset0, offset1
int lightCount;
int useBaseOver;
int bumpId0;
int bumpId1;
@ -256,7 +253,7 @@ void computeColors(inout float4 baseCol, inout float4 offsetCol, in int volIdx,
int routing = light.routing;
if (light.diffuse_specular[volIdx] == 1) // If light contributes to diffuse
{
float factor = BASE_FACTOR;
float factor = (routing & ROUTING_SUB) != 0 ? -BASE_FACTOR : BASE_FACTOR;
switch (light.dmode)
{
case LMODE_SINGLE_SIDED:
@ -266,16 +263,19 @@ void computeColors(inout float4 baseCol, inout float4 offsetCol, in int volIdx,
factor *= abs(dot(normal, lightDir));
break;
}
if (routing == ROUTING_ALPHADIFF_SUB)
diffuseAlpha -= lightColor.r * factor;
else if (routing == ROUTING_BASEDIFF_BASESPEC_ADD || routing == ROUTING_BASEDIFF_OFFSSPEC_ADD)
diffuse += lightColor * factor;
if (routing == ROUTING_OFFSDIFF_BASESPEC_ADD || routing == ROUTING_OFFSDIFF_OFFSSPEC_ADD)
specular += lightColor * factor;
if ((routing & ROUTING_ALPHA) != 0)
diffuseAlpha += lightColor.r * factor;
else
{
if ((routing & ROUTING_DIFF_TO_OFFSET) == 0)
diffuse += lightColor * factor;
else
specular += lightColor * factor;
}
}
if (light.diffuse_specular[2 + volIdx] == 1) // If light contributes to specular
{
float factor = BASE_FACTOR;
float factor = (routing & ROUTING_SUB) != 0 ? -BASE_FACTOR : BASE_FACTOR;
switch (light.smode)
{
case LMODE_SINGLE_SIDED:
@ -285,12 +285,15 @@ void computeColors(inout float4 baseCol, inout float4 offsetCol, in int volIdx,
factor *= saturate(pow(abs(dot(lightDir, reflectDir)), glossCoef[volIdx]));
break;
}
if (routing == ROUTING_ALPHADIFF_SUB)
specularAlpha -= lightColor.r * factor;
else if (routing == ROUTING_OFFSDIFF_OFFSSPEC_ADD || routing == ROUTING_BASEDIFF_OFFSSPEC_ADD)
specular += lightColor * factor;
if (routing == ROUTING_BASEDIFF_BASESPEC_ADD || routing == ROUTING_OFFSDIFF_BASESPEC_ADD)
diffuse += lightColor * factor;
if ((routing & ROUTING_ALPHA) != 0)
specularAlpha += lightColor.r * factor;
else
{
if ((routing & ROUTING_SPEC_TO_OFFSET) == 0)
diffuse += lightColor * factor;
else
specular += lightColor * factor;
}
}
}
// ambient with material
@ -399,46 +402,6 @@ struct N2PolyConstants
};
static_assert(sizeof(N2PolyConstants) == 256, "sizeof(N2PolyConstants) should be 256");
struct DX11N2Light
{
float color[4]; // 0
float direction[4]; // 16
float position[4]; // 32
int parallel; // 48
int routing; // 52
int dmode; // 56
int smode; // 60
// int4 diffuse_specular
int diffuse[2]; // 64
int specular[2]; // 72
float attnDistA; // 80
float attnDistB; // 84
float attnAngleA; // 88
float attnAngleB; // 92
int distAttnMode; // 96
int _pad[3];
// 112
};
static_assert(sizeof(DX11N2Light) == 112, "sizeof(DX11N2Light) should be 112");
struct N2LightConstants
{
DX11N2Light lights[16]; // 0
int lightCount; // 1792
int _pad0[3];
float ambientBase[2][4]; // 1808
float ambientOffset[2][4]; // 1840
// int4 ambientMaterial
int ambientMaterialBase[2]; // 1872
int ambientMaterialOffset[2]; // 1880
int useBaseOver; // 1888
int bumpId1; // 1892
int bumpId2; // 1896
int _pad3; // 1900
// 1904
};
static_assert(sizeof(N2LightConstants) == 1904, "sizeof(N2LightConstants) should be 1904");
void Naomi2Helper::init(ComPtr<ID3D11Device>& device, ComPtr<ID3D11DeviceContext> deviceContext)
{
this->deviceContext = deviceContext;
@ -451,7 +414,7 @@ void Naomi2Helper::init(ComPtr<ID3D11Device>& device, ComPtr<ID3D11DeviceContex
if (FAILED(device->CreateBuffer(&desc, nullptr, &polyConstantsBuffer.get())))
WARN_LOG(RENDERER, "Per-polygon constants buffer creation failed");
desc.ByteWidth = sizeof(N2LightConstants);
desc.ByteWidth = sizeof(N2LightModel);
desc.ByteWidth = (((desc.ByteWidth - 1) >> 4) + 1) << 4;
if (FAILED(device->CreateBuffer(&desc, nullptr, &lightConstantsBuffer.get())))
WARN_LOG(RENDERER, "Light constants buffer creation failed");
@ -481,57 +444,13 @@ void Naomi2Helper::setConstants(const PolyParam& pp, u32 polyNumber)
if (pp.lightModel != lastModel)
{
lastModel = pp.lightModel;
N2LightConstants lightConstants{};
if (pp.lightModel != nullptr)
{
const N2LightModel& lights = *pp.lightModel;
lightConstants.lightCount = lights.lightCount;
for (int i = 0; i < lights.lightCount; i++)
{
DX11N2Light& light = lightConstants.lights[i];
memcpy(light.color, lights.lights[i].color, sizeof(light.color));
memcpy(light.direction, lights.lights[i].direction, sizeof(light.direction));
memcpy(light.position, lights.lights[i].position, sizeof(light.position));
light.parallel = lights.lights[i].parallel;
light.routing = lights.lights[i].routing;
light.dmode = lights.lights[i].dmode;
light.smode = lights.lights[i].smode;
memcpy(light.diffuse, lights.lights[i].diffuse, sizeof(light.diffuse));
memcpy(light.specular, lights.lights[i].specular, sizeof(light.specular));
light.attnDistA = lights.lights[i].attnDistA;
light.attnDistB = lights.lights[i].attnDistB;
light.attnAngleA = lights.lights[i].attnAngleA;
light.attnAngleB = lights.lights[i].attnAngleB;
light.distAttnMode = lights.lights[i].distAttnMode;
}
memcpy(lightConstants.ambientBase, lights.ambientBase, sizeof(lightConstants.ambientBase));
memcpy(lightConstants.ambientOffset, lights.ambientOffset, sizeof(lightConstants.ambientOffset));
for (int i = 0; i < 2; i++)
{
lightConstants.ambientMaterialBase[i] = lights.ambientMaterialBase[i];
lightConstants.ambientMaterialOffset[i] = lights.ambientMaterialOffset[i];
}
lightConstants.useBaseOver = lights.useBaseOver;
lightConstants.bumpId1 = lights.bumpId1;
lightConstants.bumpId2 = lights.bumpId2;
}
setConstBuffer(lightConstantsBuffer, *pp.lightModel);
else
{
lightConstants.lightCount = 0;
float white[] { 1.f, 1.f, 1.f, 1.f };
float black[4]{};
for (int vol = 0; vol < 2; vol++)
{
lightConstants.ambientMaterialBase[vol] = 0;
lightConstants.ambientMaterialOffset[vol] = 0;
memcpy(lightConstants.ambientBase[vol], white, sizeof(white));
memcpy(lightConstants.ambientOffset[vol], black, sizeof(black));
}
lightConstants.useBaseOver = 0;
lightConstants.bumpId1 = -1;
lightConstants.bumpId2 = -1;
N2LightModel lightModel{};
setConstBuffer(lightConstantsBuffer, lightModel);
}
setConstBuffer(lightConstantsBuffer, lightConstants);
deviceContext->VSSetConstantBuffers(2, 1, &lightConstantsBuffer.get());
}
}

View File

@ -880,13 +880,16 @@ static void create_modvol_shader()
gl.modvol_shader.sp_ShaderColor = glGetUniformLocation(gl.modvol_shader.program, "sp_ShaderColor");
gl.modvol_shader.depth_scale = glGetUniformLocation(gl.modvol_shader.program, "depth_scale");
N2VertexSource n2vertexShader(false, true, false);
gl.n2ModVolShader.program = gl_CompileAndLink(n2vertexShader.generate().c_str(), fragmentShader.generate().c_str());
gl.n2ModVolShader.ndcMat = glGetUniformLocation(gl.n2ModVolShader.program, "ndcMat");
gl.n2ModVolShader.sp_ShaderColor = glGetUniformLocation(gl.n2ModVolShader.program, "sp_ShaderColor");
gl.n2ModVolShader.depth_scale = glGetUniformLocation(gl.n2ModVolShader.program, "depth_scale");
gl.n2ModVolShader.mvMat = glGetUniformLocation(gl.n2ModVolShader.program, "mvMat");
gl.n2ModVolShader.projMat = glGetUniformLocation(gl.n2ModVolShader.program, "projMat");
if (gl.gl_major >= 3)
{
N2VertexSource n2vertexShader(false, true, false);
gl.n2ModVolShader.program = gl_CompileAndLink(n2vertexShader.generate().c_str(), fragmentShader.generate().c_str());
gl.n2ModVolShader.ndcMat = glGetUniformLocation(gl.n2ModVolShader.program, "ndcMat");
gl.n2ModVolShader.sp_ShaderColor = glGetUniformLocation(gl.n2ModVolShader.program, "sp_ShaderColor");
gl.n2ModVolShader.depth_scale = glGetUniformLocation(gl.n2ModVolShader.program, "depth_scale");
gl.n2ModVolShader.mvMat = glGetUniformLocation(gl.n2ModVolShader.program, "mvMat");
gl.n2ModVolShader.projMat = glGetUniformLocation(gl.n2ModVolShader.program, "projMat");
}
}
bool gl_create_resources()

View File

@ -94,7 +94,7 @@ void main()
#if LIGHT_ON == 1
// FIXME need offset0 and offset1 for bump maps
if (bumpMapping == 1)
computeBumpMap(vtx_offs, vtx_offs1, vpos.xyz, vnorm, normalMat);
computeBumpMap(vtx_offs, vtx_offs1, vpos.xyz, in_normal, normalMat);
else
{
computeColors(vtx_base1, vtx_offs1, 1, vpos.xyz, vnorm);
@ -144,20 +144,12 @@ const char* N2ColorShader = R"(
#define LMODE_THIN_SURFACE 4
#define LMODE_BUMP_MAP 5
#define ROUTING_BASEDIFF_BASESPEC_ADD 0
#define ROUTING_BASEDIFF_OFFSSPEC_ADD 1
#define ROUTING_OFFSDIFF_BASESPEC_ADD 2
#define ROUTING_OFFSDIFF_OFFSSPEC_ADD 3
#define ROUTING_ALPHADIFF_ADD 4
#define ROUTING_ALPHAATTEN_ADD 5
#define ROUTING_FOGDIFF_ADD 6
#define ROUTING_FOGATTENUATION_ADD 7
#define ROUTING_BASEDIFF_BASESPEC_SUB 8
#define ROUTING_BASEDIFF_OFFSSPEC_SUB 9
#define ROUTING_OFFSDIFF_BASESPEC_SUB 10
#define ROUTING_OFFSDIFF_OFFSSPEC_SUB 11
#define ROUTING_ALPHADIFF_SUB 12
#define ROUTING_ALPHAATTEN_SUB 13
#define ROUTING_SPEC_TO_OFFSET 1
#define ROUTING_DIFF_TO_OFFSET 2
#define ROUTING_ATTENUATION 1 // not handled
#define ROUTING_FOG 2 // not handled
#define ROUTING_ALPHA 4
#define ROUTING_SUB 8
struct N2Light
{
@ -232,33 +224,39 @@ void computeColors(inout vec4 baseCol, inout vec4 offsetCol, int volIdx, vec3 po
}
if (lights[i].diffuse[volIdx] == 1)
{
float factor = BASE_FACTOR;
float factor = (lights[i].routing & ROUTING_SUB) != 0 ? -BASE_FACTOR : BASE_FACTOR;
if (lights[i].dmode == LMODE_SINGLE_SIDED)
factor *= max(dot(normal, lightDir), 0.0);
else if (lights[i].dmode == LMODE_DOUBLE_SIDED)
factor *= abs(dot(normal, lightDir));
if (lights[i].routing == ROUTING_ALPHADIFF_SUB)
diffuseAlpha -= lightColor.r * factor;
else if (lights[i].routing == ROUTING_BASEDIFF_BASESPEC_ADD || lights[i].routing == ROUTING_BASEDIFF_OFFSSPEC_ADD)
diffuse += lightColor * factor;
if (lights[i].routing == ROUTING_OFFSDIFF_BASESPEC_ADD || lights[i].routing == ROUTING_OFFSDIFF_OFFSSPEC_ADD)
specular += lightColor * factor;
if ((lights[i].routing & ROUTING_ALPHA) != 0)
diffuseAlpha += lightColor.r * factor;
else
{
if ((lights[i].routing & ROUTING_DIFF_TO_OFFSET) == 0)
diffuse += lightColor * factor;
else
specular += lightColor * factor;
}
}
if (lights[i].specular[volIdx] == 1)
{
float factor = BASE_FACTOR;
float factor = (lights[i].routing & ROUTING_SUB) != 0 ? -BASE_FACTOR : BASE_FACTOR;
if (lights[i].smode == LMODE_SINGLE_SIDED)
factor *= clamp(pow(max(dot(lightDir, reflectDir), 0.0), glossCoef[volIdx]), 0.0, 1.0);
else if (lights[i].smode == LMODE_DOUBLE_SIDED)
factor *= clamp(pow(abs(dot(lightDir, reflectDir)), glossCoef[volIdx]), 0.0, 1.0);
if (lights[i].routing == ROUTING_ALPHADIFF_SUB)
specularAlpha -= lightColor.r * factor;
else if (lights[i].routing == ROUTING_OFFSDIFF_OFFSSPEC_ADD || lights[i].routing == ROUTING_BASEDIFF_OFFSSPEC_ADD)
specular += lightColor * factor;
if (lights[i].routing == ROUTING_BASEDIFF_BASESPEC_ADD || lights[i].routing == ROUTING_OFFSDIFF_BASESPEC_ADD)
diffuse += lightColor * factor;
if ((lights[i].routing & ROUTING_ALPHA) != 0)
specularAlpha += lightColor.r * factor;
else
{
if ((lights[i].routing & ROUTING_SPEC_TO_OFFSET) == 0)
diffuse += lightColor * factor;
else
specular += lightColor * factor;
}
}
}
// ambient with material
@ -306,6 +304,7 @@ void computeBumpMap(inout vec4 color0, vec4 color1, vec3 position, vec3 normal,
// TODO
//if (bumpId0 == -1)
return;
normal = normalize(normal);
vec3 tangent = color0.xyz;
if (tangent.x > 0.5)
tangent.x -= 1.0;
@ -313,7 +312,7 @@ void computeBumpMap(inout vec4 color0, vec4 color1, vec3 position, vec3 normal,
tangent.y -= 1.0;
if (tangent.z > 0.5)
tangent.z -= 1.0;
tangent = normalize(normalMat * vec4(tangent, 0.0)).xyz;
tangent = normalize(tangent);
vec3 bitangent = color1.xyz;
if (bitangent.x > 0.5)
bitangent.x -= 1.0;
@ -321,16 +320,17 @@ void computeBumpMap(inout vec4 color0, vec4 color1, vec3 position, vec3 normal,
bitangent.y -= 1.0;
if (bitangent.z > 0.5)
bitangent.z -= 1.0;
bitangent = normalize(normalMat * vec4(bitangent, 0.0)).xyz;
bitangent = normalize(bitangent);
float scaleDegree = color0.w;
float scaleOffset = color1.w;
vec3 lightDir; // direction to the light
if (lights[bumpId0].parallel == 1)
lightDir = normalize(lights[bumpId0].direction.xyz);
lightDir = lights[bumpId0].direction.xyz;
else
lightDir = normalize(lights[bumpId0].position.xyz - position);
lightDir = lights[bumpId0].position.xyz - position;
lightDir = normalize(lightDir * mat3(normalMat));
float n = dot(lightDir, normal);
float cosQ = dot(lightDir, tangent);
@ -349,6 +349,7 @@ void computeBumpMap(inout vec4 color0, vec4 color1, vec3 position, vec3 normal,
color0.g = k3;
color0.b = q / PI / 2.0;
color0.a = k1;
color0 = clamp(color0, 0.0, 1.0);
}
)";

View File

@ -278,11 +278,10 @@ void Drawer::UploadMainBuffer(const VertexShaderUniforms& vertexUniforms, const
offsets.fragmentUniformOffset = packer.addUniform(&fragmentUniforms, sizeof(fragmentUniforms));
std::vector<u8> n2uniforms;
std::vector<u8> n2lights;
if (settings.platform.isNaomi2())
{
packNaomi2Uniforms(packer, offsets, n2uniforms, false);
offsets.lightsOffset = packNaomi2Lights(packer, n2lights);
offsets.lightsOffset = packNaomi2Lights(packer);
}
BufferData *buffer = GetMainBuffer(packer.size());

View File

@ -139,48 +139,20 @@ protected:
offsets.naomi2TrModVolOffset = offsets.naomi2OpaqueOffset + trMvOffset;
}
vk::DeviceSize packNaomi2Lights(BufferPacker& packer, std::vector<u8>& n2lights)
vk::DeviceSize packNaomi2Lights(BufferPacker& packer)
{
size_t n2LightSize = sizeof(VkN2LightConstants) + align(sizeof(VkN2LightConstants), GetContext()->GetUniformBufferAlignment());
n2lights.resize(pvrrc.lightModels.used() * n2LightSize);
size_t bufIdx = 0;
for (const N2LightModel& lights : pvrrc.lightModels)
{
VkN2LightConstants& vkLights = *(VkN2LightConstants *)&n2lights[bufIdx];
vkLights.lightCount = lights.lightCount;
for (int i = 0; i < lights.lightCount; i++)
{
VkN2Light& vkLight = vkLights.lights[i];
const N2Light& light = lights.lights[i];
memcpy(vkLight.color, light.color, sizeof(vkLight.color));
memcpy(vkLight.direction, light.direction, sizeof(vkLight.direction));
memcpy(vkLight.position, light.position, sizeof(vkLight.position));
vkLight.parallel = light.parallel;
vkLight.routing = light.routing;
vkLight.dmode = light.dmode;
vkLight.smode = light.smode;
memcpy(vkLight.diffuse, light.diffuse, sizeof(vkLight.diffuse));
memcpy(vkLight.specular, light.specular, sizeof(vkLight.specular));
vkLight.attnDistA = light.attnDistA;
vkLight.attnDistB = light.attnDistB;
vkLight.attnAngleA = light.attnAngleA;
vkLight.attnAngleB = light.attnAngleB;
vkLight.distAttnMode = light.distAttnMode;
}
memcpy(vkLights.ambientBase, lights.ambientBase, sizeof(vkLights.ambientBase));
memcpy(vkLights.ambientOffset, lights.ambientOffset, sizeof(vkLights.ambientOffset));
for (int i = 0; i < 2; i++)
{
vkLights.ambientMaterialBase[i] = lights.ambientMaterialBase[i];
vkLights.ambientMaterialOffset[i] = lights.ambientMaterialOffset[i];
}
vkLights.useBaseOver = lights.useBaseOver;
vkLights.bumpId1 = lights.bumpId1;
vkLights.bumpId2 = lights.bumpId2;
size_t n2LightSize = sizeof(N2LightModel) + align(sizeof(N2LightModel), GetContext()->GetUniformBufferAlignment());
if (n2LightSize == sizeof(N2LightModel))
return packer.addUniform(pvrrc.lightModels.head(), pvrrc.lightModels.bytes());
bufIdx += n2LightSize;
vk::DeviceSize offset = (vk::DeviceSize)-1;
for (const N2LightModel& model : pvrrc.lightModels)
{
vk::DeviceSize o = packer.addUniform(&model, sizeof(N2LightModel));
if (offset == (vk::DeviceSize)-1)
offset = o;
}
return packer.addUniform(n2lights.data(), bufIdx);
return offset;
}
vk::Rect2D baseScissor;

View File

@ -238,11 +238,10 @@ void OITDrawer::UploadMainBuffer(const OITDescriptorSets::VertexShaderUniforms&
offsets.polyParamsOffset = packer.addStorage(trPolyParams.data(), offsets.polyParamsSize);
std::vector<u8> n2uniforms;
std::vector<u8> n2lights;
if (settings.platform.isNaomi2())
{
packNaomi2Uniforms(packer, offsets, n2uniforms, true);
offsets.lightsOffset = packNaomi2Lights(packer, n2lights);
offsets.lightsOffset = packNaomi2Lights(packer);
}
BufferData *buffer = GetMainBuffer(packer.size());

View File

@ -188,8 +188,8 @@ public:
if (poly.lightModel != nullptr)
{
size = sizeof(VkN2LightConstants) + align(sizeof(VkN2LightConstants), uniformAlignment);
lightBufferInfo = vk::DescriptorBufferInfo{ buffer, lightOffset + (poly.lightModel - pvrrc.lightModels.head()) * size, sizeof(VkN2LightConstants) };
size = sizeof(N2LightModel) + align(sizeof(N2LightModel), uniformAlignment);
lightBufferInfo = vk::DescriptorBufferInfo{ buffer, lightOffset + (poly.lightModel - pvrrc.lightModels.head()) * size, sizeof(N2LightModel) };
writeDescriptorSets.emplace_back(perPolyDescSet, 3, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &lightBufferInfo, nullptr);
}
// TODO no light

View File

@ -105,8 +105,8 @@ public:
if (poly.lightModel != nullptr)
{
size = sizeof(VkN2LightConstants) + align(sizeof(VkN2LightConstants), uniformAlignment);
lightBufferInfo = vk::DescriptorBufferInfo{ buffer, lightOffset + (poly.lightModel - pvrrc.lightModels.head()) * size, sizeof(VkN2LightConstants) };
size = sizeof(N2LightModel) + align(sizeof(N2LightModel), uniformAlignment);
lightBufferInfo = vk::DescriptorBufferInfo{ buffer, lightOffset + (poly.lightModel - pvrrc.lightModels.head()) * size, sizeof(N2LightModel) };
writeDescriptorSets.emplace_back(perPolyDescSet, 3, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &lightBufferInfo, nullptr);
}
// TODO no light

View File

@ -351,20 +351,12 @@ layout (std140, set = 1, binding = 2) uniform N2VertexShaderUniforms
#define LMODE_THIN_SURFACE 4
#define LMODE_BUMP_MAP 5
#define ROUTING_BASEDIFF_BASESPEC_ADD 0
#define ROUTING_BASEDIFF_OFFSSPEC_ADD 1
#define ROUTING_OFFSDIFF_BASESPEC_ADD 2
#define ROUTING_OFFSDIFF_OFFSSPEC_ADD 3
#define ROUTING_ALPHADIFF_ADD 4
#define ROUTING_ALPHAATTEN_ADD 5
#define ROUTING_FOGDIFF_ADD 6
#define ROUTING_FOGATTENUATION_ADD 7
#define ROUTING_BASEDIFF_BASESPEC_SUB 8
#define ROUTING_BASEDIFF_OFFSSPEC_SUB 9
#define ROUTING_OFFSDIFF_BASESPEC_SUB 10
#define ROUTING_OFFSDIFF_OFFSSPEC_SUB 11
#define ROUTING_ALPHADIFF_SUB 12
#define ROUTING_ALPHAATTEN_SUB 13
#define ROUTING_SPEC_TO_OFFSET 1
#define ROUTING_DIFF_TO_OFFSET 2
#define ROUTING_ATTENUATION 1 // not handled
#define ROUTING_FOG 2 // not handled
#define ROUTING_ALPHA 4
#define ROUTING_SUB 8
struct N2Light
{
@ -442,33 +434,39 @@ void computeColors(inout vec4 baseCol, inout vec4 offsetCol, in int volIdx, in v
}
if (n2Lights.lights[i].diffuse[volIdx] == 1)
{
float factor = BASE_FACTOR;
float factor = (n2Lights.lights[i].routing & ROUTING_SUB) != 0 ? -BASE_FACTOR : BASE_FACTOR;
if (n2Lights.lights[i].dmode == LMODE_SINGLE_SIDED)
factor *= max(dot(normal, lightDir), 0.0);
else if (n2Lights.lights[i].dmode == LMODE_DOUBLE_SIDED)
factor *= abs(dot(normal, lightDir));
if (n2Lights.lights[i].routing == ROUTING_ALPHADIFF_SUB)
diffuseAlpha -= lightColor.r * factor;
else if (n2Lights.lights[i].routing == ROUTING_BASEDIFF_BASESPEC_ADD || n2Lights.lights[i].routing == ROUTING_BASEDIFF_OFFSSPEC_ADD)
diffuse += lightColor * factor;
if (n2Lights.lights[i].routing == ROUTING_OFFSDIFF_BASESPEC_ADD || n2Lights.lights[i].routing == ROUTING_OFFSDIFF_OFFSSPEC_ADD)
specular += lightColor * factor;
if ((n2Lights.lights[i].routing & ROUTING_ALPHA) != 0)
diffuseAlpha += lightColor.r * factor;
else
{
if ((n2Lights.lights[i].routing & ROUTING_DIFF_TO_OFFSET) == 0)
diffuse += lightColor * factor;
else
specular += lightColor * factor;
}
}
if (n2Lights.lights[i].specular[volIdx] == 1)
{
float factor = BASE_FACTOR;
float factor = (n2Lights.lights[i].routing & ROUTING_SUB) != 0 ? -BASE_FACTOR : BASE_FACTOR;
if (n2Lights.lights[i].smode == LMODE_SINGLE_SIDED)
factor *= clamp(pow(max(dot(lightDir, reflectDir), 0.0), n2Uniform.glossCoef[volIdx]), 0.0, 1.0);
else if (n2Lights.lights[i].smode == LMODE_DOUBLE_SIDED)
factor *= clamp(pow(abs(dot(lightDir, reflectDir)), n2Uniform.glossCoef[volIdx]), 0.0, 1.0);
if (n2Lights.lights[i].routing == ROUTING_ALPHADIFF_SUB)
specularAlpha -= lightColor.r * factor;
else if (n2Lights.lights[i].routing == ROUTING_OFFSDIFF_OFFSSPEC_ADD || n2Lights.lights[i].routing == ROUTING_BASEDIFF_OFFSSPEC_ADD)
specular += lightColor * factor;
if (n2Lights.lights[i].routing == ROUTING_BASEDIFF_BASESPEC_ADD || n2Lights.lights[i].routing == ROUTING_OFFSDIFF_BASESPEC_ADD)
diffuse += lightColor * factor;
if ((n2Lights.lights[i].routing & ROUTING_ALPHA) != 0)
specularAlpha += lightColor.r * factor;
else
{
if ((n2Lights.lights[i].routing & ROUTING_SPEC_TO_OFFSET) == 0)
diffuse += lightColor * factor;
else
specular += lightColor * factor;
}
}
}
// ambient with material
@ -514,7 +512,7 @@ void computeEnvMap(inout vec2 uv, in vec3 position, in vec3 normal)
void computeBumpMap(inout vec4 color0, in vec4 color1, in vec3 position, in vec3 normal, in mat4 normalMat)
{
// TODO
if (n2Lights.bumpId0 == -1)
//if (n2Lights.bumpId0 == -1)
return;
normal = normalize(normal);
vec3 tangent = color0.xyz;
@ -524,7 +522,6 @@ void computeBumpMap(inout vec4 color0, in vec4 color1, in vec3 position, in vec3
tangent.y -= 1.0;
if (tangent.z > 0.5)
tangent.z -= 1.0;
//tangent = normalize(normalMat * vec4(tangent, 0.0)).xyz;
tangent = normalize(tangent);
vec3 bitangent = color1.xyz;
if (bitangent.x > 0.5)
@ -533,7 +530,6 @@ void computeBumpMap(inout vec4 color0, in vec4 color1, in vec3 position, in vec3
bitangent.y -= 1.0;
if (bitangent.z > 0.5)
bitangent.z -= 1.0;
//bitangent = normalize(normalMat * vec4(bitangent, 0.0)).xyz;
bitangent = normalize(bitangent);
float scaleDegree = color0.w;
@ -563,6 +559,7 @@ void computeBumpMap(inout vec4 color0, in vec4 color1, in vec3 position, in vec3
color0.g = k3;
color0.b = q / PI / 2.0;
color0.a = k1;
color0 = clamp(color0, 0.0, 1.0);
}
)";

View File

@ -93,44 +93,6 @@ struct N2VertexShaderUniforms
int modelSpecular[2];
};
// std140 alignment required
struct VkN2Light
{
float color[4];
float direction[4];
float position[4];
int parallel;
int routing;
int dmode;
int smode;
int diffuse[2];
int specular[2];
float attnDistA;
float attnDistB;
float attnAngleA;
float attnAngleB;
int distAttnMode;
int _pad[3];
};
// std140 alignment required
struct VkN2LightConstants
{
VkN2Light lights[16];
float ambientBase[2][4];
float ambientOffset[2][4];
int ambientMaterialBase[2];
int ambientMaterialOffset[2];
int lightCount;
int useBaseOver;
int bumpId1;
int bumpId2;
};
class ShaderManager
{
public:

View File

@ -258,7 +258,8 @@ protected:
curTexture->UploadToGPU(width, height, (u8*)pb.data(), false);
curTexture->SetCommandBuffer(nullptr);
Vertex *vtx = ctx->rend.verts.Append(4);
// Use background poly vtx and param
Vertex *vtx = ctx->rend.verts.head();
vtx[0].x = 0.f;
vtx[0].y = 0.f;
vtx[0].z = 0.1f;
@ -280,13 +281,13 @@ protected:
vtx[3].v = 1.f;
u32 *idx = ctx->rend.idx.Append(4);
idx[0] = ctx->rend.verts.used() - 4;
idx[1] = idx[0] + 1;
idx[2] = idx[1] + 1;
idx[3] = idx[2] + 1;
idx[0] = 0;
idx[1] = 1;
idx[2] = 2;
idx[3] = 3;
PolyParam *pp = ctx->rend.global_param_op.Append(1);
pp->first = ctx->rend.idx.used() - 4;
PolyParam *pp = ctx->rend.global_param_op.head();
pp->first = 0;
pp->count = 4;
pp->isp.full = 0;
@ -314,7 +315,7 @@ protected:
pass->autosort = false;
pass->mvo_count = 0;
pass->mvo_tr_count = 0;
pass->op_count = ctx->rend.global_param_op.used();
pass->op_count = 1;
pass->pt_count = 0;
pass->tr_count = 0;