Improve modifier volume parsing and drawing logic.

Parse modifier volumes similarily to other polys (first, count, params).
Draw all triangles in one shot and use quad to sum up instead of
redrawing entire strip. Use OR operation for open volumes/quads
(Soulcalibur).
This commit is contained in:
Flyinghead 2018-06-26 14:24:45 +02:00
parent 846d02d9d2
commit 7c93727b5e
4 changed files with 84 additions and 106 deletions

View File

@ -37,10 +37,11 @@ struct PolyParam
//float zMin,zMax; //float zMin,zMax;
}; };
struct ModParam struct ModifierVolumeParam
{ {
u32 first; //entry index , holds vertex/pos data u32 first;
u32 count; u32 count;
ISP_Modvol isp;
}; };
struct ModTriangle struct ModTriangle
@ -117,7 +118,7 @@ struct rend_context
List<Vertex> verts; List<Vertex> verts;
List<u16> idx; List<u16> idx;
List<ModTriangle> modtrig; List<ModTriangle> modtrig;
List<ISP_Modvol> global_param_mvo; List<ModifierVolumeParam> global_param_mvo;
List<PolyParam> global_param_op; List<PolyParam> global_param_op;
List<PolyParam> global_param_pt; List<PolyParam> global_param_pt;

View File

@ -768,12 +768,9 @@ public:
{ {
CurrentPP=&nullPP; CurrentPP=&nullPP;
CurrentPPlist=0; CurrentPPlist=0;
if (ListType==ListType_Opaque_Modifier_Volume)
{ if (ListType == ListType_Opaque_Modifier_Volume)
ISP_Modvol p; EndModVol();
p.id=vdrc.modtrig.used();
*vdrc.global_param_mvo.Append()=p;
}
} }
/* /*
@ -1368,17 +1365,34 @@ public:
#endif #endif
} }
//ModVolumes // Modifier Volumes Vertex handlers
static void EndModVol()
{
List<ModifierVolumeParam> *list = NULL;
if (CurrentList == ListType_Opaque_Modifier_Volume)
list = &vdrc.global_param_mvo;
else
return;
if (list->used() > 0)
{
ModifierVolumeParam *p = &(list->head()[list->used() - 1]);
p->count = vdrc.modtrig.used() - p->first;
}
}
//Mod Volume Vertex handlers
static void StartModVol(TA_ModVolParam* param) static void StartModVol(TA_ModVolParam* param)
{ {
if (CurrentList!=ListType_Opaque_Modifier_Volume) EndModVol();
ModifierVolumeParam *p = NULL;
if (CurrentList == ListType_Opaque_Modifier_Volume)
p = vdrc.global_param_mvo.Append();
else
return; return;
ISP_Modvol* p=vdrc.global_param_mvo.Append(); p->isp.full = param->isp.full;
p->full=param->isp.full; p->isp.VolumeLast = param->pcw.Volume != 0;
p->VolumeLast=param->pcw.Volume; p->first = vdrc.modtrig.used();
p->id=vdrc.modtrig.used();
} }
__forceinline __forceinline
static void AppendModVolVertexA(TA_ModVolA* mvv) static void AppendModVolVertexA(TA_ModVolA* mvv)

View File

@ -812,35 +812,46 @@ void DrawSorted(bool multipass)
10 -> 00 10 -> 00
11 -> 01 11 -> 01
*/ */
void SetMVS_Mode(u32 mv_mode,ISP_Modvol ispc) void SetMVS_Mode(ModifierVolumeMode mv_mode, ISP_Modvol ispc)
{ {
if (mv_mode==0) //normal trigs if (mv_mode == Xor)
{ {
//set states // set states
glcache.Enable(GL_DEPTH_TEST); glcache.Enable(GL_DEPTH_TEST);
//write only bit 1 // write only bit 1
glcache.StencilMask(2); glcache.StencilMask(2);
//no stencil testing // no stencil testing
glcache.StencilFunc(GL_ALWAYS,0,2); glcache.StencilFunc(GL_ALWAYS, 0, 2);
//count the number of pixels in front of the Z buffer (xor zpass) // count the number of pixels in front of the Z buffer (xor zpass)
glcache.StencilOp(GL_KEEP,GL_KEEP,GL_INVERT); glcache.StencilOp(GL_KEEP, GL_KEEP, GL_INVERT);
//Cull mode needs to be set // Cull mode needs to be set
SetCull(ispc.CullMode);
}
else if (mv_mode == Or)
{
// set states
glcache.Enable(GL_DEPTH_TEST);
// write only bit 1
glcache.StencilMask(2);
// no stencil testing
glcache.StencilFunc(GL_ALWAYS, 2, 2);
// Or'ing of all triangles
glcache.StencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
// Cull mode needs to be set
SetCull(ispc.CullMode); SetCull(ispc.CullMode);
} }
else else
{ {
//1 (last in) or 2 (last out) // Inclusion or Exclusion volume
//each triangle forms the last of a volume
//common states // no depth test
//no depth test
glcache.Disable(GL_DEPTH_TEST); glcache.Disable(GL_DEPTH_TEST);
//write bits 1:0 // write bits 1:0
glcache.StencilMask(3); glcache.StencilMask(3);
if (mv_mode==1) if (mv_mode == Inclusion)
{ {
// Inclusion volume // Inclusion volume
//res : old : final //res : old : final
@ -849,9 +860,9 @@ void SetMVS_Mode(u32 mv_mode,ISP_Modvol ispc)
//1 : 0 : 01 //1 : 0 : 01
//1 : 1 : 01 //1 : 1 : 01
//if (1<=st) st=1; else st=0; // if (1<=st) st=1; else st=0;
glcache.StencilFunc(GL_LEQUAL,1,3); glcache.StencilFunc(GL_LEQUAL,1,3);
glcache.StencilOp(GL_ZERO,GL_ZERO,GL_REPLACE); glcache.StencilOp(GL_ZERO, GL_ZERO, GL_REPLACE);
} }
else else
{ {
@ -869,7 +880,7 @@ void SetMVS_Mode(u32 mv_mode,ISP_Modvol ispc)
// if (1 == st) st = 1; else st = 0; // if (1 == st) st = 1; else st = 0;
glcache.StencilFunc(GL_EQUAL, 1, 3); glcache.StencilFunc(GL_EQUAL, 1, 3);
glcache.StencilOp(GL_ZERO, GL_ZERO, GL_REPLACE); glcache.StencilOp(GL_ZERO, GL_ZERO, GL_KEEP);
} }
} }
} }
@ -939,85 +950,35 @@ void DrawModVols(int first, int count)
} }
else else
{ {
/* //Full emulation
mode :
normal trig : flip
last *in* : flip, merge*in* &clear from last merge
last *out* : flip, merge*out* &clear from last merge
*/
/* glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
Do not write to color ModifierVolumeParam* params = &pvrrc.global_param_mvo.head()[first];
Do not write to depth
read from stencil bits 1:0 for (u32 cmv = 0; cmv < count; cmv++)
write to stencil bits 1:0
*/
glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
if (0)
{ {
//simple single level stencil ModifierVolumeParam& param = params[cmv];
glcache.Enable(GL_STENCIL_TEST);
glcache.StencilFunc(GL_ALWAYS,0x1,0x1);
glcache.StencilOp(GL_KEEP,GL_KEEP,GL_INVERT);
glcache.StencilMask(0x1);
SetCull(0);
glDrawArrays(GL_TRIANGLES, first, count * 3);
}
else if (true)
{
//Full emulation
//the *out* mode is buggy
u32 mod_base=0; //cur start triangle if (param.count == 0)
u32 mod_last=0; //last merge continue;
u32 cmv_count = count - 1; u32 mv_mode = param.isp.DepthMode;
ISP_Modvol* params = &pvrrc.global_param_mvo.head()[first];
//ISP_Modvol if (!param.isp.VolumeLast && mv_mode > 0)
for (u32 cmv=0;cmv<cmv_count;cmv++) SetMVS_Mode(Or, param.isp); // OR'ing (open volume or quad)
else
SetMVS_Mode(Xor, param.isp); // XOR'ing (closed volume)
glDrawArrays(GL_TRIANGLES, param.first * 3, param.count * 3);
if (mv_mode == 1 || mv_mode == 2)
{ {
// Sum the area
ISP_Modvol ispc=params[cmv]; SetMVS_Mode(mv_mode == 1 ? Inclusion : Exclusion, param.isp);
mod_base=ispc.id; // Use the background poly as a quad to do the sum up
u32 sz=params[cmv+1].id-mod_base; SetupMainVBO();
if (sz == 0) glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
continue; SetupModvolVBO();
u32 mv_mode = ispc.DepthMode;
if (mv_mode==0) //normal trigs
{
SetMVS_Mode(0,ispc);
//Render em (counts intersections)
//verifyc(dev->DrawPrimitiveUP(D3DPT_TRIANGLELIST,sz,pvrrc.modtrig.data+mod_base,3*4));
glDrawArrays(GL_TRIANGLES,mod_base*3,sz*3);
}
else if (mv_mode<3)
{
while(sz)
{
//merge and clear all the prev. stencil bits
//Count Intersections (last poly)
SetMVS_Mode(0,ispc);
glDrawArrays(GL_TRIANGLES,mod_base*3,3);
//Sum the area
SetMVS_Mode(mv_mode,ispc);
glDrawArrays(GL_TRIANGLES,mod_last*3,(mod_base-mod_last+1)*3);
//update pointers
mod_last=mod_base+1;
sz--;
mod_base++;
}
}
} }
} }
//disable culling //disable culling

View File

@ -126,3 +126,5 @@ int GetProgramID(u32 cp_AlphaTest, u32 pp_ClipTestMode,
bool CompilePipelineShader(PipelineShader* s); bool CompilePipelineShader(PipelineShader* s);
#define TEXTURE_LOAD_ERROR 0 #define TEXTURE_LOAD_ERROR 0
GLuint loadPNG(const string& subpath, int &width, int &height); GLuint loadPNG(const string& subpath, int &width, int &height);
enum ModifierVolumeMode { Xor, Or, Inclusion, Exclusion, ModeCount };