Skip to content

Commit

Permalink
Initial pass of avatar rendering (with no textures)
Browse files Browse the repository at this point in the history
  • Loading branch information
dpogue committed May 5, 2023
1 parent b0146cf commit aa8f192
Show file tree
Hide file tree
Showing 7 changed files with 339 additions and 177 deletions.
167 changes: 8 additions & 159 deletions Sources/Plasma/FeatureLib/pfDXPipeline/plDXPipeline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,13 +282,10 @@ plProfile_Extern(LayChange);
plProfile_Extern(DrawTriangles);
plProfile_Extern(MatChange);
plProfile_Extern(NumSkin);

plProfile_CreateCounterNoReset("Reload", "PipeC", PipeReload);

plProfile_Extern(PipeReload);
plProfile_Extern(PrepShadows);
plProfile_Extern(PrepDrawable);
plProfile_Extern(Skin);
plProfile_Extern(AvatarSort);
plProfile_Extern(ClearLights);
plProfile_Extern(RenderSpan);
plProfile_Extern(MergeCheck);
Expand All @@ -304,6 +301,13 @@ plProfile_Extern(RenderPrim);
plProfile_Extern(PlateMgr);
plProfile_Extern(DebugText);
plProfile_Extern(Reset);
plProfile_Extern(AvRTPoolUsed);
plProfile_Extern(AvRTPoolCount);
plProfile_Extern(AvRTPoolRes);
plProfile_Extern(AvRTShrinkTime);
plProfile_Extern(SpanMerge);
plProfile_Extern(MatLightState);
plProfile_Extern(EmptyList);

plProfile_CreateMemCounter("DefMem", "PipeC", DefaultMem);
plProfile_CreateMemCounter("ManMem", "PipeC", ManagedMem);
Expand All @@ -313,18 +317,10 @@ plProfile_CreateMemCounterReset("fTexUsed", "PipeC", fTexUsed);
plProfile_CreateMemCounterReset("fTexManaged", "PipeC", fTexManaged);
plProfile_CreateMemCounterReset("fVtxUsed", "PipeC", fVtxUsed);
plProfile_CreateMemCounterReset("fVtxManaged", "PipeC", fVtxManaged);
plProfile_CreateCounter("Merge", "PipeC", SpanMerge);
plProfile_CreateCounter("TexNum", "PipeC", NumTex);
plProfile_CreateCounter("LiState", "PipeC", MatLightState);
plProfile_CreateCounter("AvatarFaces", "PipeC", AvatarFaces);
plProfile_CreateCounter("VertexChange", "PipeC", VertexChange);
plProfile_CreateCounter("IndexChange", "PipeC", IndexChange);
plProfile_CreateCounter("DynVBuffs", "PipeC", DynVBuffs);
plProfile_CreateCounter("EmptyList", "PipeC", EmptyList);
plProfile_CreateCounter("AvRTPoolUsed", "PipeC", AvRTPoolUsed);
plProfile_CreateCounter("AvRTPoolCount", "PipeC", AvRTPoolCount);
plProfile_CreateCounter("AvRTPoolRes", "PipeC", AvRTPoolRes);
plProfile_CreateCounter("AvRTShrinkTime", "PipeC", AvRTShrinkTime);

#ifndef PLASMA_EXTERNAL_RELEASE
/// Fun inlines for keeping track of surface creation/deletion memory
Expand Down Expand Up @@ -2316,153 +2312,6 @@ bool plDXPipeline::PreRender(plDrawable* drawable, std::vector<int16_t>& visLis
return !visList.empty();
}

struct plSortFace
{
uint16_t fIdx[3];
float fDist;
};

struct plCompSortFace
{
bool operator()( const plSortFace& lhs, const plSortFace& rhs) const
{
return lhs.fDist > rhs.fDist;
}
};

// IAvatarSort /////////////////////////////////////////////////////////////////////////
// We handle avatar sort differently from the rest of the face sort. The reason is that
// within the single avatar index buffer, we want to only sort the faces of spans requesting
// a sort, and sort them in place.
// Contrast that with the normal scene translucency sort. There, we sort all the spans in a drawble,
// then we sort all the faces in that drawable, then for each span in the sorted span list, we extract
// the faces for that span appending onto the index buffer. This gives great efficiency because
// only the visible faces are sorted and they wind up packed into the front of the index buffer, which
// permits more batching. See plDrawableSpans::SortVisibleSpans.
// For the avatar, it's generally the case that all the avatar is visible or not, and there is only
// one material, so neither of those efficiencies is helpful. Moreover, for the avatar the faces we
// want sorted are a tiny subset of the avatar's faces. Moreover, and most importantly, for the avatar, we
// want to preserve the order that spans are drawn, so, for example, the opaque base head will always be
// drawn before the translucent hair fringe, which will always be drawn before the pink clear plastic baseball cap.
bool plDXPipeline::IAvatarSort(plDrawableSpans* d, const std::vector<int16_t>& visList)
{
plProfile_BeginTiming(AvatarSort);
for (int16_t visIdx : visList)
{
hsAssert(d->GetSpan(visIdx)->fTypeMask & plSpan::kIcicleSpan, "Unknown type for sorting faces");

plIcicle* span = (plIcicle*)d->GetSpan(visIdx);

if( span->fProps & plSpan::kPartialSort )
{
hsAssert(d->GetBufferGroup(span->fGroupIdx)->AreIdxVolatile(), "Badly setup buffer group - set PartialSort too late?");

const hsPoint3 viewPos = GetViewPositionWorld();

plGBufferGroup* group = d->GetBufferGroup(span->fGroupIdx);

plDXVertexBufferRef* vRef = (plDXVertexBufferRef*)group->GetVertexBufferRef(span->fVBufferIdx);

const uint8_t* vdata = vRef->fData;
const uint32_t stride = vRef->fVertexSize;

const int numTris = span->fILength/3;

static std::vector<plSortFace> sortScratch;
sortScratch.resize(numTris);

plProfile_IncCount(AvatarFaces, numTris);

//
// Have three very similar sorts here, differing only on where the "position" of
// each triangle is defined, either as the center of the triangle, the nearest
// point on the triangle, or the farthest point on the triangle.
// Having tried all three on the avatar (the only thing this sort is used on),
// the best results surprisingly came from using the center of the triangle.
uint16_t* indices = group->GetIndexBufferData(span->fIBufferIdx) + span->fIStartIdx;
int j;
for( j = 0; j < numTris; j++ )
{
#if 1 // TRICENTER
uint16_t idx = *indices++;
sortScratch[j].fIdx[0] = idx;
hsPoint3 pos = *(hsPoint3*)(vdata + idx * stride);

idx = *indices++;
sortScratch[j].fIdx[1] = idx;
pos += *(hsPoint3*)(vdata + idx * stride);

idx = *indices++;
sortScratch[j].fIdx[2] = idx;
pos += *(hsPoint3*)(vdata + idx * stride);

pos *= 0.3333f;

sortScratch[j].fDist = hsVector3(&pos, &viewPos).MagnitudeSquared();
#elif 0 // NEAREST
uint16_t idx = *indices++;
sortScratch[j].fIdx[0] = idx;
hsPoint3 pos = *(hsPoint3*)(vdata + idx * stride);
float dist = hsVector3(&pos, &viewPos).MagnitudeSquared();
float minDist = dist;

idx = *indices++;
sortScratch[j].fIdx[1] = idx;
pos = *(hsPoint3*)(vdata + idx * stride);
dist = hsVector3(&pos, &viewPos).MagnitudeSquared();
if( dist < minDist )
minDist = dist;

idx = *indices++;
sortScratch[j].fIdx[2] = idx;
pos = *(hsPoint3*)(vdata + idx * stride);
dist = hsVector3(&pos, &viewPos).MagnitudeSquared();
if( dist < minDist )
minDist = dist;

sortScratch[j].fDist = minDist;
#elif 1 // FURTHEST
uint16_t idx = *indices++;
sortScratch[j].fIdx[0] = idx;
hsPoint3 pos = *(hsPoint3*)(vdata + idx * stride);
float dist = hsVector3(&pos, &viewPos).MagnitudeSquared();
float maxDist = dist;

idx = *indices++;
sortScratch[j].fIdx[1] = idx;
pos = *(hsPoint3*)(vdata + idx * stride);
dist = hsVector3(&pos, &viewPos).MagnitudeSquared();
if( dist > maxDist )
maxDist = dist;

idx = *indices++;
sortScratch[j].fIdx[2] = idx;
pos = *(hsPoint3*)(vdata + idx * stride);
dist = hsVector3(&pos, &viewPos).MagnitudeSquared();
if( dist > maxDist )
maxDist = dist;

sortScratch[j].fDist = maxDist;
#endif // SORTTYPES
}

std::sort(sortScratch.begin(), sortScratch.end(), plCompSortFace());

indices = group->GetIndexBufferData(span->fIBufferIdx) + span->fIStartIdx;
for (const plSortFace& iter : sortScratch)
{
*indices++ = iter.fIdx[0];
*indices++ = iter.fIdx[1];
*indices++ = iter.fIdx[2];
}

group->DirtyIndexBuffer(span->fIBufferIdx);
}
}
plProfile_EndTiming(AvatarSort);
return true;
}

// PrepForRender //////////////////////////////////////////////////////////////////
// Make sure the given drawable and each of the spans to be drawn (as noted in the
// indices in visList) is ready to be rendered.
Expand Down
1 change: 0 additions & 1 deletion Sources/Plasma/FeatureLib/pfDXPipeline/plDXPipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,6 @@ class plDXPipeline : public pl3DPipeline<plDXDevice>
// Visualization of active occluders
void IMakeOcclusionSnap();

bool IAvatarSort(plDrawableSpans* d, const std::vector<int16_t>& visList);
void IBlendVertsIntoBuffer( plSpan* span,
hsMatrix44* matrixPalette, int numMatrices,
const uint8_t *src, uint8_t format, uint32_t srcStride,
Expand Down
15 changes: 14 additions & 1 deletion Sources/Plasma/FeatureLib/pfGLPipeline/plGLDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ bool plGLDevice::InitDevice()
// ANGLE.
//
// On Linux, this should be true with mesa or nvidia drivers.
if (epoxy_has_egl())
if (epoxy_has_egl() && fContextType == kNone)
InitEGLDevice(this);
#endif

Expand Down Expand Up @@ -456,6 +456,19 @@ bool plGLDevice::BeginRender()
return false;
}

#ifdef USE_EGL
if (fContextType == kEGL) {
EGLDisplay display = static_cast<EGLDisplay>(fDisplay);
EGLContext context = static_cast<EGLContext>(fContext);
EGLSurface surface = static_cast<EGLSurface>(fSurface);

if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
fErrorMsg = "Failed to attach EGL context to surface";
return false;
}
} //else
#endif

return true;
}

Expand Down
Loading

0 comments on commit aa8f192

Please sign in to comment.