mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 14:51:51 +00:00
- use hardware clip planes to split translucent walls and sprites by 3D floor planes.
This method has the advantage that it also works for models, xy-billboarded sprites and walls that require complex splitting of the polygon. The old method using actual polygon splitting only works for strictly vertical data that could be trivially split in two.
This commit is contained in:
parent
45526c2769
commit
cf7cb4f00f
1 changed files with 59 additions and 53 deletions
|
@ -307,12 +307,10 @@ void GLDrawList::SortWallIntoPlane(SortNode * head,SortNode * sort)
|
|||
{
|
||||
GLFlat * fh=&flats[drawitems[head->itemindex].index];
|
||||
GLWall * ws=&walls[drawitems[sort->itemindex].index];
|
||||
GLWall * ws1;
|
||||
|
||||
bool ceiling = fh->z > FIXED2FLOAT(viewz);
|
||||
|
||||
|
||||
if (ws->ztop[0]>fh->z && ws->zbottom[0]<fh->z)
|
||||
if ((ws->ztop[0] > fh->z || ws->ztop[1] > fh->z) && (ws->zbottom[0] < fh->z || ws->zbottom[1] < fh->z))
|
||||
{
|
||||
// We have to split this wall!
|
||||
|
||||
|
@ -321,23 +319,7 @@ void GLDrawList::SortWallIntoPlane(SortNode * head,SortNode * sort)
|
|||
GLWall w = *ws;
|
||||
AddWall(&w);
|
||||
|
||||
ws1=&walls[walls.Size()-1];
|
||||
ws=&walls[drawitems[sort->itemindex].index]; // may have been reallocated!
|
||||
float newtexv = ws->uplft.v + ((ws->lolft.v - ws->uplft.v) / (ws->zbottom[0] - ws->ztop[0])) * (fh->z - ws->ztop[0]);
|
||||
|
||||
// I make the very big assumption here that translucent walls in sloped sectors
|
||||
// and 3D-floors never coexist in the same level. If that were the case this
|
||||
// code would become extremely more complicated.
|
||||
if (!ceiling)
|
||||
{
|
||||
ws->ztop[1] = ws1->zbottom[1] = ws->ztop[0] = ws1->zbottom[0] = fh->z;
|
||||
ws->uprgt.v = ws1->lorgt.v = ws->uplft.v = ws1->lolft.v = newtexv;
|
||||
}
|
||||
else
|
||||
{
|
||||
ws1->ztop[1] = ws->zbottom[1] = ws1->ztop[0] = ws->zbottom[0] = fh->z;
|
||||
ws1->uplft.v = ws->lolft.v = ws1->uprgt.v = ws->lorgt.v=newtexv;
|
||||
}
|
||||
// Splitting is done in the shader with clip planes.
|
||||
|
||||
SortNode * sort2 = SortNodes.GetNew();
|
||||
memset(sort2, 0, sizeof(SortNode));
|
||||
|
@ -366,29 +348,16 @@ void GLDrawList::SortSpriteIntoPlane(SortNode * head,SortNode * sort)
|
|||
{
|
||||
GLFlat * fh=&flats[drawitems[head->itemindex].index];
|
||||
GLSprite * ss=&sprites[drawitems[sort->itemindex].index];
|
||||
GLSprite * ss1;
|
||||
|
||||
bool ceiling = fh->z > FIXED2FLOAT(viewz);
|
||||
|
||||
if (ss->z1>fh->z && ss->z2<fh->z)
|
||||
if ((ss->z1>fh->z && ss->z2<fh->z) || ss->modelframe)
|
||||
{
|
||||
// We have to split this sprite!
|
||||
// We have to split this sprite
|
||||
GLSprite s=*ss;
|
||||
AddSprite(&s);
|
||||
ss1=&sprites[sprites.Size()-1];
|
||||
ss=&sprites[drawitems[sort->itemindex].index]; // may have been reallocated!
|
||||
float newtexv=ss->vt + ((ss->vb-ss->vt)/(ss->z2-ss->z1))*(fh->z-ss->z1);
|
||||
AddSprite(&s); // add a copy to avoid reallocation issues.
|
||||
|
||||
if (!ceiling)
|
||||
{
|
||||
ss->z1=ss1->z2=fh->z;
|
||||
ss->vt=ss1->vb=newtexv;
|
||||
}
|
||||
else
|
||||
{
|
||||
ss1->z1=ss->z2=fh->z;
|
||||
ss1->vt=ss->vb=newtexv;
|
||||
}
|
||||
// Splitting is done in the shader with clip planes.
|
||||
|
||||
SortNode * sort2=SortNodes.GetNew();
|
||||
memset(sort2,0,sizeof(SortNode));
|
||||
|
@ -729,11 +698,32 @@ void GLDrawList::DoDraw(int pass, int i, bool trans)
|
|||
//==========================================================================
|
||||
void GLDrawList::DoDrawSorted(SortNode * head)
|
||||
{
|
||||
do
|
||||
float clipsplit[2];
|
||||
int relation = 0;
|
||||
float z = 0.f;
|
||||
|
||||
gl_RenderState.GetClipSplit(clipsplit);
|
||||
|
||||
if (drawitems[head->itemindex].rendertype == GLDIT_FLAT)
|
||||
{
|
||||
z = flats[drawitems[head->itemindex].index].z;
|
||||
relation = z > FIXED2FLOAT(viewz)? 1 : -1;
|
||||
}
|
||||
|
||||
|
||||
// left is further away, i.e. for stuff above viewz its z coordinate higher, for stuff below viewz its z coordinate is lower
|
||||
if (head->left)
|
||||
{
|
||||
if (relation == -1)
|
||||
{
|
||||
gl_RenderState.SetClipSplit(clipsplit[0], z); // render below: set flat as top clip plane
|
||||
}
|
||||
else if (relation == 1)
|
||||
{
|
||||
gl_RenderState.SetClipSplit(z, clipsplit[1]); // render above: set flat as bottom clip plane
|
||||
}
|
||||
DoDrawSorted(head->left);
|
||||
gl_RenderState.SetClipSplit(clipsplit);
|
||||
}
|
||||
DoDraw(GLPASS_TRANSLUCENT, head->itemindex, true);
|
||||
if (head->equal)
|
||||
|
@ -745,8 +735,20 @@ void GLDrawList::DoDrawSorted(SortNode * head)
|
|||
ehead=ehead->equal;
|
||||
}
|
||||
}
|
||||
// right is closer, i.e. for stuff above viewz its z coordinate is lower, for stuff below viewz its z coordinate is higher
|
||||
if (head->right)
|
||||
{
|
||||
if (relation == 1)
|
||||
{
|
||||
gl_RenderState.SetClipSplit(clipsplit[0], z); // render below: set flat as top clip plane
|
||||
}
|
||||
else if (relation == -1)
|
||||
{
|
||||
gl_RenderState.SetClipSplit(z, clipsplit[1]); // render above: set flat as bottom clip plane
|
||||
}
|
||||
DoDrawSorted(head->right);
|
||||
gl_RenderState.SetClipSplit(clipsplit);
|
||||
}
|
||||
while ((head=head->right));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -763,7 +765,11 @@ void GLDrawList::DrawSorted()
|
|||
MakeSortList();
|
||||
sorted=DoSort(SortNodes[SortNodeStart]);
|
||||
}
|
||||
glEnable(GL_CLIP_DISTANCE2);
|
||||
glEnable(GL_CLIP_DISTANCE3);
|
||||
DoDrawSorted(sorted);
|
||||
glDisable(GL_CLIP_DISTANCE2);
|
||||
glDisable(GL_CLIP_DISTANCE3);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
Loading…
Reference in a new issue