implemented GS alpha test emu for gl3

This commit is contained in:
aap 2020-04-28 14:09:26 +02:00
parent 438397f411
commit a312007893
6 changed files with 107 additions and 19 deletions

View File

@ -55,9 +55,11 @@ void *createVertexDeclaration(VertexElement *elements);
void destroyVertexDeclaration(void *delaration);
uint32 getDeclaration(void *declaration, VertexElement *elements);
void drawInst(d3d9::InstanceDataHeader *header, d3d9::InstanceData *inst);
void drawInst_simple(d3d9::InstanceDataHeader *header, d3d9::InstanceData *inst);
// Emulate PS2 GS alpha test FB_ONLY case: failed alpha writes to frame- but not to depth buffer
void drawInst_GSemu(d3d9::InstanceDataHeader *header, InstanceData *inst);
// This one switches between the above two depending on render state;
void drawInst(d3d9::InstanceDataHeader *header, d3d9::InstanceData *inst);

View File

@ -128,6 +128,7 @@ struct RwStateCache {
uint32 alphaTestEnable;
uint32 alphaFunc;
bool32 textureAlpha;
bool32 blendEnable;
uint32 srcblend, destblend;
uint32 zwrite;
uint32 ztest;
@ -135,6 +136,11 @@ struct RwStateCache {
uint32 fogEnable;
float32 fogStart;
float32 fogEnd;
// emulation of PS2 GS
bool32 gsalpha;
uint32 gsalpharef;
RwRasterStateCache texstage[MAXNUMSTAGES];
};
static RwStateCache rwStateCache;
@ -157,6 +163,21 @@ static uint32 blendMap[] = {
GL_SRC_ALPHA_SATURATE,
};
void
setAlphaBlend(bool32 enable)
{
if(rwStateCache.blendEnable != enable){
rwStateCache.blendEnable = enable;
(enable ? glEnable : glDisable)(GL_BLEND);
}
}
bool32
getAlphaBlend(void)
{
return rwStateCache.blendEnable;
}
static void
setDepthTest(bool32 enable)
{
@ -224,7 +245,7 @@ setVertexAlpha(bool32 enable)
{
if(rwStateCache.vertexAlpha != enable){
if(!rwStateCache.textureAlpha){
(enable ? glEnable : glDisable)(GL_BLEND);
setAlphaBlend(enable);
setAlphaTest(enable);
}
rwStateCache.vertexAlpha = enable;
@ -343,7 +364,7 @@ setRasterStageOnly(uint32 stage, Raster *raster)
if(alpha != rwStateCache.textureAlpha){
rwStateCache.textureAlpha = alpha;
if(!rwStateCache.vertexAlpha){
(alpha ? glEnable : glDisable)(GL_BLEND);
setAlphaBlend(alpha);
setAlphaTest(alpha);
}
}
@ -392,7 +413,7 @@ setRasterStage(uint32 stage, Raster *raster)
if(alpha != rwStateCache.textureAlpha){
rwStateCache.textureAlpha = alpha;
if(!rwStateCache.vertexAlpha){
(alpha ? glEnable : glDisable)(GL_BLEND);
setAlphaBlend(alpha);
setAlphaTest(alpha);
}
}
@ -492,6 +513,11 @@ setRenderState(int32 state, void *pvalue)
stateDirty = 1;
}
break;
case GSALPHATEST:
rwStateCache.gsalpha = value;
break;
case GSALPHATESTREF:
rwStateCache.gsalpharef = value;
}
}
@ -551,6 +577,12 @@ getRenderState(int32 state)
case ALPHATESTREF:
val = (uint32)(uniformState.alphaRef*255.0f);
break;
case GSALPHATEST:
val = rwStateCache.gsalpha;
break;
case GSALPHATESTREF:
val = rwStateCache.gsalpharef;
break;
default:
val = 0;
}
@ -568,13 +600,16 @@ resetRenderState(void)
uniformState.fogEnd = 0.0f;
uniformState.fogRange = 0.0f;
uniformState.fogColor = { 1.0f, 1.0f, 1.0f, 1.0f };
rwStateCache.gsalpha = 0;
rwStateCache.gsalpharef = 128;
stateDirty = 1;
rwStateCache.vertexAlpha = 0;
rwStateCache.textureAlpha = 0;
glDisable(GL_BLEND);
rwStateCache.alphaTestEnable = 0;
rwStateCache.blendEnable = 0;
glDisable(GL_BLEND);
rwStateCache.srcblend = BLENDSRCALPHA;
rwStateCache.destblend = BLENDINVSRCALPHA;
glBlendFunc(blendMap[rwStateCache.srcblend], blendMap[rwStateCache.destblend]);

View File

@ -85,9 +85,7 @@ matfxDefaultRender(InstanceDataHeader *header, InstanceData *inst)
rw::SetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 0xFF);
flushCache();
glDrawElements(header->primType, inst->numIndex,
GL_UNSIGNED_SHORT, (void*)(uintptr)inst->offset);
drawInst(header, inst);
}
static Frame *lastEnvFrame;
@ -152,9 +150,7 @@ matfxEnvRender(InstanceDataHeader *header, InstanceData *inst, MatFX::Env *env)
rw::SetRenderState(VERTEXALPHA, 1);
rw::SetRenderState(SRCBLEND, BLENDONE);
flushCache();
glDrawElements(header->primType, inst->numIndex,
GL_UNSIGNED_SHORT, (void*)(uintptr)inst->offset);
drawInst(header, inst);
rw::SetRenderState(SRCBLEND, BLENDSRCALPHA);
}

View File

@ -19,7 +19,58 @@
namespace rw {
namespace gl3 {
#define MAX_LIGHTS 8
#define MAX_LIGHTS
void
drawInst_simple(InstanceDataHeader *header, InstanceData *inst)
{
flushCache();
glDrawElements(header->primType, inst->numIndex,
GL_UNSIGNED_SHORT, (void*)(uintptr)inst->offset);
}
// Emulate PS2 GS alpha test FB_ONLY case: failed alpha writes to frame- but not to depth buffer
void
drawInst_GSemu(InstanceDataHeader *header, InstanceData *inst)
{
uint32 hasAlpha;
int alphafunc, alpharef, gsalpharef;
int zwrite;
hasAlpha = getAlphaBlend();
if(hasAlpha){
zwrite = rw::GetRenderState(rw::ZWRITEENABLE);
alphafunc = rw::GetRenderState(rw::ALPHATESTFUNC);
if(zwrite){
alpharef = rw::GetRenderState(rw::ALPHATESTREF);
gsalpharef = rw::GetRenderState(rw::GSALPHATESTREF);
SetRenderState(rw::ALPHATESTFUNC, rw::ALPHAGREATEREQUAL);
SetRenderState(rw::ALPHATESTREF, gsalpharef);
drawInst_simple(header, inst);
SetRenderState(rw::ALPHATESTFUNC, rw::ALPHALESS);
SetRenderState(rw::ZWRITEENABLE, 0);
drawInst_simple(header, inst);
SetRenderState(rw::ZWRITEENABLE, 1);
SetRenderState(rw::ALPHATESTFUNC, alphafunc);
SetRenderState(rw::ALPHATESTREF, alpharef);
}else{
SetRenderState(rw::ALPHATESTFUNC, rw::ALPHAALWAYS);
drawInst_simple(header, inst);
SetRenderState(rw::ALPHATESTFUNC, alphafunc);
}
}else
drawInst_simple(header, inst);
}
void
drawInst(InstanceDataHeader *header, InstanceData *inst)
{
if(rw::GetRenderState(rw::GSALPHATEST))
drawInst_GSemu(header, inst);
else
drawInst_simple(header, inst);
}
void
setAttribPointers(AttribDesc *attribDescs, int32 numAttribs)
@ -102,9 +153,7 @@ defaultRenderCB(Atomic *atomic, InstanceDataHeader *header)
rw::SetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 0xFF);
flushCache();
glDrawElements(header->primType, inst->numIndex,
GL_UNSIGNED_SHORT, (void*)(uintptr)inst->offset);
drawInst(header, inst);
inst++;
}
disableAttribPointers(header->attribDesc, header->numAttribs);

View File

@ -309,9 +309,7 @@ skinRenderCB(Atomic *atomic, InstanceDataHeader *header)
rw::SetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 0xFF);
flushCache();
glDrawElements(header->primType, inst->numIndex,
GL_UNSIGNED_SHORT, (void*)(uintptr)inst->offset);
drawInst(header, inst);
inst++;
}
disableAttribPointers(header->attribDesc, header->numAttribs);

View File

@ -171,10 +171,11 @@ int32 setLights(WorldLights *lightData);
// per Mesh
void setTexture(int32 n, Texture *tex);
void setAlphaBlend(bool32 enable);
bool32 getAlphaBlend(void);
uint32 bindTexture(uint32 texid);
void flushCache(void);
#endif
@ -194,6 +195,13 @@ void defaultUninstanceCB(Geometry *geo, InstanceDataHeader *header);
void defaultRenderCB(Atomic *atomic, InstanceDataHeader *header);
int32 lightingCB(Atomic *atomic);
void drawInst_simple(InstanceDataHeader *header, InstanceData *inst);
// Emulate PS2 GS alpha test FB_ONLY case: failed alpha writes to frame- but not to depth buffer
void drawInst_GSemu(InstanceDataHeader *header, InstanceData *inst);
// This one switches between the above two depending on render state;
void drawInst(InstanceDataHeader *header, InstanceData *inst);
void *destroyNativeData(void *object, int32, int32);
ObjPipeline *makeDefaultPipeline(void);