better 2d/3d blending, but only in windows using the EXT_blend_func_separate
This commit is contained in:
parent
8ee198006f
commit
fe0413f8ad
|
@ -93,14 +93,16 @@ static unsigned int textureMode=0;
|
||||||
|
|
||||||
//raw ds format poly attributes, installed from the display list
|
//raw ds format poly attributes, installed from the display list
|
||||||
static u32 polyAttr=0,textureFormat=0, texturePalette=0;
|
static u32 polyAttr=0,textureFormat=0, texturePalette=0;
|
||||||
//derived values extracted from polyattr
|
|
||||||
|
//derived values extracted from polyattr etc
|
||||||
static bool wireframe=false, alpha31=false;
|
static bool wireframe=false, alpha31=false;
|
||||||
static unsigned int polyID=0;
|
static unsigned int polyID=0;
|
||||||
static unsigned int depthFuncMode=0;
|
static unsigned int depthFuncMode=0;
|
||||||
static unsigned int envMode=0;
|
static unsigned int envMode=0;
|
||||||
static unsigned int cullingMask=0;
|
static unsigned int cullingMask=0;
|
||||||
static int alphaDepthWrite = 0;
|
static bool alphaDepthWrite;
|
||||||
static unsigned int lightMask=0;
|
static unsigned int lightMask=0;
|
||||||
|
static bool isTranslucent;
|
||||||
|
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -119,6 +121,7 @@ OGLEXT(PFNGLATTACHSHADERPROC,glAttachShader)
|
||||||
OGLEXT(PFNGLLINKPROGRAMPROC,glLinkProgram)
|
OGLEXT(PFNGLLINKPROGRAMPROC,glLinkProgram)
|
||||||
OGLEXT(PFNGLUSEPROGRAMPROC,glUseProgram)
|
OGLEXT(PFNGLUSEPROGRAMPROC,glUseProgram)
|
||||||
OGLEXT(PFNGLGETSHADERINFOLOGPROC,glGetShaderInfoLog)
|
OGLEXT(PFNGLGETSHADERINFOLOGPROC,glGetShaderInfoLog)
|
||||||
|
OGLEXT(PFNGLBLENDFUNCSEPARATEEXTPROC,glBlendFuncSeparateEXT)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -263,8 +266,6 @@ static char Init(void)
|
||||||
if(!BEGINGL())
|
if(!BEGINGL())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
glClearColor (0.f, 0.f, 0.f, 1.f);
|
|
||||||
|
|
||||||
glPixelStorei(GL_PACK_ALIGNMENT,8);
|
glPixelStorei(GL_PACK_ALIGNMENT,8);
|
||||||
|
|
||||||
xglEnable (GL_NORMALIZE);
|
xglEnable (GL_NORMALIZE);
|
||||||
|
@ -280,6 +281,8 @@ static char Init(void)
|
||||||
if (glGetError() != GL_NO_ERROR)
|
if (glGetError() != GL_NO_ERROR)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
INITOGLEXT(PFNGLCREATESHADERPROC,glCreateShader)
|
INITOGLEXT(PFNGLCREATESHADERPROC,glCreateShader)
|
||||||
INITOGLEXT(X_PFNGLGETSHADERSOURCEPROC,glShaderSource)
|
INITOGLEXT(X_PFNGLGETSHADERSOURCEPROC,glShaderSource)
|
||||||
|
@ -289,6 +292,13 @@ static char Init(void)
|
||||||
INITOGLEXT(PFNGLLINKPROGRAMPROC,glLinkProgram)
|
INITOGLEXT(PFNGLLINKPROGRAMPROC,glLinkProgram)
|
||||||
INITOGLEXT(PFNGLUSEPROGRAMPROC,glUseProgram)
|
INITOGLEXT(PFNGLUSEPROGRAMPROC,glUseProgram)
|
||||||
INITOGLEXT(PFNGLGETSHADERINFOLOGPROC,glGetShaderInfoLog)
|
INITOGLEXT(PFNGLGETSHADERINFOLOGPROC,glGetShaderInfoLog)
|
||||||
|
INITOGLEXT(PFNGLBLENDFUNCSEPARATEEXTPROC,glBlendFuncSeparateEXT)
|
||||||
|
|
||||||
|
//we want to use alpha destination blending so we can track the last-rendered alpha value
|
||||||
|
if(glBlendFuncSeparateEXT)
|
||||||
|
{
|
||||||
|
glBlendFuncSeparateEXT(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_DST_ALPHA);
|
||||||
|
}
|
||||||
|
|
||||||
if(glCreateShader && glShaderSource && glCompileShader && glCreateProgram && glAttachShader && glLinkProgram && glUseProgram && glGetShaderInfoLog)
|
if(glCreateShader && glShaderSource && glCompileShader && glCreateProgram && glAttachShader && glLinkProgram && glUseProgram && glGetShaderInfoLog)
|
||||||
{
|
{
|
||||||
|
@ -328,6 +338,14 @@ static char Init(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
if(!glBlendFuncSeparateEXT)
|
||||||
|
#endif
|
||||||
|
glClearColor(0, 0, 0, 1);
|
||||||
|
#ifdef _WIN32
|
||||||
|
else glClearColor(0, 0, 0, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
ENDGL();
|
ENDGL();
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -808,7 +826,7 @@ static u32 stencilStateSet = -1;
|
||||||
|
|
||||||
static void BeginRenderPoly()
|
static void BeginRenderPoly()
|
||||||
{
|
{
|
||||||
int enableDepthWrite = 1;
|
bool enableDepthWrite = true;
|
||||||
u32 tmp=0;
|
u32 tmp=0;
|
||||||
|
|
||||||
xglDepthFunc (depthFuncMode);
|
xglDepthFunc (depthFuncMode);
|
||||||
|
@ -825,10 +843,6 @@ static void BeginRenderPoly()
|
||||||
if (!wireframe)
|
if (!wireframe)
|
||||||
{
|
{
|
||||||
xglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
|
xglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
|
||||||
//non-31 alpha polys are translucent
|
|
||||||
if(!alpha31)
|
|
||||||
enableDepthWrite = alphaDepthWrite;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -837,22 +851,17 @@ static void BeginRenderPoly()
|
||||||
|
|
||||||
setTexture(textureFormat, texturePalette);
|
setTexture(textureFormat, texturePalette);
|
||||||
|
|
||||||
//a5i3 or a3i5 textures are translucent
|
alphaDepthWrite = false;
|
||||||
alphaDepthWrite = 0; //zero - as a hack, we are never going to write depth buffer for alpha values
|
if(isTranslucent)
|
||||||
//this is the best we can do right now until we can sort and display translucent polys last like we're supposed to
|
|
||||||
//(here is a sample case which illustrates the problem)
|
|
||||||
//1. draw something opaque in the distance
|
|
||||||
//2. draw something translucent in the foreground
|
|
||||||
//3. draw something opaque in the middle ground
|
|
||||||
if(textureMode ==1 || textureMode == 6)
|
|
||||||
enableDepthWrite = alphaDepthWrite;
|
enableDepthWrite = alphaDepthWrite;
|
||||||
|
enableDepthWrite = false;
|
||||||
|
|
||||||
//handle shadow polys
|
//handle shadow polys
|
||||||
if(envMode == 3)
|
if(envMode == 3)
|
||||||
{
|
{
|
||||||
xglEnable(GL_STENCIL_TEST);
|
xglEnable(GL_STENCIL_TEST);
|
||||||
if(polyID == 0) {
|
if(polyID == 0) {
|
||||||
enableDepthWrite = 1;
|
enableDepthWrite = true;
|
||||||
if(stencilStateSet!=0) {
|
if(stencilStateSet!=0) {
|
||||||
stencilStateSet = 0;
|
stencilStateSet = 0;
|
||||||
//when the polyID is zero, we are writing the shadow mask.
|
//when the polyID is zero, we are writing the shadow mask.
|
||||||
|
@ -863,7 +872,7 @@ static void BeginRenderPoly()
|
||||||
glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
|
glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
enableDepthWrite = 0;
|
enableDepthWrite = false;
|
||||||
if(stencilStateSet!=1) {
|
if(stencilStateSet!=1) {
|
||||||
stencilStateSet = 1;
|
stencilStateSet = 1;
|
||||||
//when the polyid is nonzero, we are drawing the shadow poly.
|
//when the polyid is nonzero, we are drawing the shadow poly.
|
||||||
|
@ -907,7 +916,7 @@ static void InstallPolygonAttrib(unsigned long val)
|
||||||
envMode = (val&0x30)>>4;
|
envMode = (val&0x30)>>4;
|
||||||
|
|
||||||
// overwrite depth on alpha pass
|
// overwrite depth on alpha pass
|
||||||
alphaDepthWrite = BIT11(val);
|
alphaDepthWrite = BIT11(val)!=0;
|
||||||
|
|
||||||
// depth test function
|
// depth test function
|
||||||
depthFuncMode = depthFunc[BIT14(val)];
|
depthFuncMode = depthFunc[BIT14(val)];
|
||||||
|
@ -934,8 +943,8 @@ static void Control()
|
||||||
else
|
else
|
||||||
glAlphaFunc (GL_GREATER, 0);
|
glAlphaFunc (GL_GREATER, 0);
|
||||||
|
|
||||||
if(gfx3d.enableAlphaBlending) {
|
if(gfx3d.enableAlphaBlending)
|
||||||
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
{
|
||||||
glEnable (GL_BLEND);
|
glEnable (GL_BLEND);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -961,13 +970,14 @@ static void Render()
|
||||||
u32 lastTextureFormat, lastTexturePalette, lastPolyAttr;
|
u32 lastTextureFormat, lastTexturePalette, lastPolyAttr;
|
||||||
|
|
||||||
for(int i=0;i<gfx3d.polylist->count;i++) {
|
for(int i=0;i<gfx3d.polylist->count;i++) {
|
||||||
POLY *poly = &gfx3d.polylist->list[i];
|
POLY *poly = &gfx3d.polylist->list[gfx3d.indexlist[i]];
|
||||||
int type = poly->type;
|
int type = poly->type;
|
||||||
|
|
||||||
//a very macro-level state caching approach:
|
//a very macro-level state caching approach:
|
||||||
//these are the only things which control the GPU rendering state.
|
//these are the only things which control the GPU rendering state.
|
||||||
if(i==0 || lastTextureFormat != poly->texParam || lastTexturePalette != poly->texPalette || lastPolyAttr != poly->polyAttr)
|
if(i==0 || lastTextureFormat != poly->texParam || lastTexturePalette != poly->texPalette || lastPolyAttr != poly->polyAttr)
|
||||||
{
|
{
|
||||||
|
isTranslucent = poly->isTranslucent();
|
||||||
InstallPolygonAttrib(lastPolyAttr=poly->polyAttr);
|
InstallPolygonAttrib(lastPolyAttr=poly->polyAttr);
|
||||||
lastTextureFormat = textureFormat = poly->texParam;
|
lastTextureFormat = textureFormat = poly->texParam;
|
||||||
lastTexturePalette = texturePalette = poly->texPalette;
|
lastTexturePalette = texturePalette = poly->texPalette;
|
||||||
|
@ -1094,6 +1104,11 @@ static void GetLine (int line, u16* dst)
|
||||||
g=min(255,g);
|
g=min(255,g);
|
||||||
b=min(255,b);
|
b=min(255,b);
|
||||||
|
|
||||||
|
//debug: display alpha channel
|
||||||
|
//u32 r = screen3D[t+3];
|
||||||
|
//u32 g = screen3D[t+3];
|
||||||
|
//u32 b = screen3D[t+3];
|
||||||
|
|
||||||
dst[i] = ((b>>3)<<10) | ((g>>3)<<5) | (r>>3);
|
dst[i] = ((b>>3)<<10) | ((g>>3)<<5) | (r>>3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1411,6 +1411,22 @@ void gfx3d_glFlush(unsigned long v)
|
||||||
gfx3d.polylist = polylist;
|
gfx3d.polylist = polylist;
|
||||||
gfx3d.vertlist = vertlist;
|
gfx3d.vertlist = vertlist;
|
||||||
|
|
||||||
|
//we need to sort the poly list with alpha polys last
|
||||||
|
//first, look for alpha polys
|
||||||
|
int polycount = polylist->count;
|
||||||
|
int ctr=0;
|
||||||
|
for(int i=0;i<polycount;i++) {
|
||||||
|
POLY &poly = polylist->list[i];
|
||||||
|
if(!poly.isTranslucent())
|
||||||
|
gfx3d.indexlist[ctr++] = i;
|
||||||
|
}
|
||||||
|
//then look for translucent polys
|
||||||
|
for(int i=0;i<polycount;i++) {
|
||||||
|
POLY &poly = polylist->list[i];
|
||||||
|
if(poly.isTranslucent())
|
||||||
|
gfx3d.indexlist[ctr++] = i;
|
||||||
|
}
|
||||||
|
|
||||||
//switch to the new lists
|
//switch to the new lists
|
||||||
twiddleLists();
|
twiddleLists();
|
||||||
}
|
}
|
||||||
|
@ -1421,6 +1437,7 @@ void gfx3d_VBlankSignal()
|
||||||
//so, if we have a redraw pending, now is a safe time to do it
|
//so, if we have a redraw pending, now is a safe time to do it
|
||||||
if(!flushPending) return;
|
if(!flushPending) return;
|
||||||
flushPending = false;
|
flushPending = false;
|
||||||
|
|
||||||
gpu3D->NDS_3D_Render();
|
gpu3D->NDS_3D_Render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,20 @@ struct POLY {
|
||||||
int vertIndexes[4]; //up to four verts can be referenced by this poly
|
int vertIndexes[4]; //up to four verts can be referenced by this poly
|
||||||
u32 polyAttr, texParam, texPalette; //the hardware rendering params
|
u32 polyAttr, texParam, texPalette; //the hardware rendering params
|
||||||
float projMatrix[16];
|
float projMatrix[16];
|
||||||
|
|
||||||
|
bool isTranslucent()
|
||||||
|
{
|
||||||
|
//alpha != 31 -> translucent
|
||||||
|
if((polyAttr&0x001F0000) != 0x001F0000)
|
||||||
|
return true;
|
||||||
|
int texFormat = (texParam>>26)&7;
|
||||||
|
|
||||||
|
//a5i3 or a3i5 -> translucent
|
||||||
|
if(texFormat==1 || texFormat==6)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define POLYLIST_SIZE 6000
|
#define POLYLIST_SIZE 6000
|
||||||
|
@ -76,6 +90,7 @@ struct GFX3D
|
||||||
|
|
||||||
POLYLIST* polylist;
|
POLYLIST* polylist;
|
||||||
VERTLIST* vertlist;
|
VERTLIST* vertlist;
|
||||||
|
int indexlist[POLYLIST_SIZE];
|
||||||
|
|
||||||
bool wbuffer, sortmode;
|
bool wbuffer, sortmode;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue