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:
parent
846d02d9d2
commit
7c93727b5e
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 };
|
||||||
|
|
Loading…
Reference in New Issue