void RenderPolyScene::Render(PolyPortalViewpoint *viewpoint) { PolyPortalViewpoint *oldviewpoint = CurrentViewpoint; CurrentViewpoint = viewpoint; PolyRenderThread *thread = PolyRenderer::Instance()->Threads.MainThread(); CurrentViewpoint->ObjectsStart = thread->TranslucentObjects.size(); CurrentViewpoint->SectorPortalsStart = thread->SectorPortals.size(); CurrentViewpoint->LinePortalsStart = thread->LinePortals.size(); PolyCullCycles.Clock(); Cull.CullScene(CurrentViewpoint->PortalEnterSector, CurrentViewpoint->PortalEnterLine); PolyCullCycles.Unclock(); RenderSectors(); PolyMaskedCycles.Clock(); const auto &rviewpoint = PolyRenderer::Instance()->Viewpoint; for (uint32_t sectorIndex : Cull.SeenSectors) { sector_t *sector = &PolyRenderer::Instance()->Level->sectors[sectorIndex]; for (AActor *thing = sector->thinglist; thing != nullptr; thing = thing->snext) { if (!RenderPolySprite::IsThingCulled(thing)) { int spritenum = thing->sprite; bool isPicnumOverride = thing->picnum.isValid(); FSpriteModelFrame *modelframe = isPicnumOverride ? nullptr : FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED)); double distanceSquared = (thing->Pos() - rviewpoint.Pos).LengthSquared(); if (r_modelscene && modelframe && distanceSquared < model_distance_cull) { AddModel(thread, thing, distanceSquared, thing->Pos()); } else { DVector2 left, right; if (!RenderPolySprite::GetLine(thing, left, right)) continue; AddSprite(thread, thing, distanceSquared, left, right); } } } } PolyMaskedCycles.Unclock(); CurrentViewpoint->ObjectsEnd = thread->TranslucentObjects.size(); CurrentViewpoint->SectorPortalsEnd = thread->SectorPortals.size(); CurrentViewpoint->LinePortalsEnd = thread->LinePortals.size(); Skydome.Render(thread, CurrentViewpoint->WorldToView, CurrentViewpoint->WorldToClip); RenderPortals(); RenderTranslucent(); CurrentViewpoint = oldviewpoint; }
void RenderPolySprite::Render(PolyRenderThread *thread, AActor *thing, subsector_t *sub, uint32_t stencilValue, float t1, float t2) { if (r_modelscene) { const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; int spritenum = thing->sprite; bool isPicnumOverride = thing->picnum.isValid(); FSpriteModelFrame *modelframe = isPicnumOverride ? nullptr : FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED)); if (modelframe && (thing->Pos() - viewpoint.Pos).LengthSquared() < model_distance_cull) { DVector3 pos = thing->InterpolatedPosition(viewpoint.TicFrac); PolyRenderModel(thread, PolyRenderer::Instance()->Scene.CurrentViewpoint->WorldToClip, stencilValue, (float)pos.X, (float)pos.Y, (float)pos.Z, modelframe, thing); return; } } DVector2 line[2]; if (!GetLine(thing, line[0], line[1])) return; const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; DVector3 thingpos = thing->InterpolatedPosition(viewpoint.TicFrac); double posZ = thingpos.Z; uint32_t spritetype = (thing->renderflags & RF_SPRITETYPEMASK); if (spritetype == RF_FACESPRITE) posZ -= thing->Floorclip; if (thing->flags2 & MF2_FLOATBOB) posZ += thing->GetBobOffset(viewpoint.TicFrac); bool flipTextureX = false; FTexture *tex = GetSpriteTexture(thing, flipTextureX); if (tex == nullptr || tex->UseType == ETextureType::Null) return; double thingyscalemul = thing->Scale.Y / tex->Scale.Y; double spriteHeight = thingyscalemul * tex->GetHeight(); posZ -= (tex->GetHeight() - tex->GetTopOffsetPo()) * thingyscalemul; posZ = PerformSpriteClipAdjustment(thing, thingpos, spriteHeight, posZ); //double depth = 1.0; //visstyle_t visstyle = GetSpriteVisStyle(thing, depth); // Rumor has it that AlterWeaponSprite needs to be called with visstyle passed in somewhere around here.. //R_SetColorMapLight(visstyle.BaseColormap, 0, visstyle.ColormapNum << FRACBITS); TriVertex *vertices = thread->FrameMemory->AllocMemory<TriVertex>(4); bool foggy = false; int actualextralight = foggy ? 0 : viewpoint.extralight << 4; std::pair<float, float> offsets[4] = { { t1, 1.0f }, { t2, 1.0f }, { t2, 0.0f }, { t1, 0.0f }, }; DVector2 points[2] = { line[0] * (1.0 - t1) + line[1] * t1, line[0] * (1.0 - t2) + line[1] * t2 }; for (int i = 0; i < 4; i++) { auto &p = (i == 0 || i == 3) ? points[0] : points[1]; vertices[i].x = (float)p.X; vertices[i].y = (float)p.Y; vertices[i].z = (float)(posZ + spriteHeight * offsets[i].second); vertices[i].w = 1.0f; vertices[i].u = (float)(offsets[i].first * tex->Scale.X); vertices[i].v = (float)((1.0f - offsets[i].second) * tex->Scale.Y); if (flipTextureX) vertices[i].u = 1.0f - vertices[i].u; } bool fullbrightSprite = ((thing->renderflags & RF_FULLBRIGHT) || (thing->flags5 & MF5_BRIGHT)); int lightlevel = fullbrightSprite ? 255 : thing->Sector->lightlevel + actualextralight; PolyDrawArgs args; SetDynlight(thing, args); args.SetLight(GetColorTable(sub->sector->Colormap, sub->sector->SpecialColors[sector_t::sprites], true), lightlevel, PolyRenderer::Instance()->Light.SpriteGlobVis(foggy), fullbrightSprite); args.SetStencilTestValue(stencilValue); if ((thing->renderflags & RF_ZDOOMTRANS) && r_UseVanillaTransparency) args.SetStyle(LegacyRenderStyles[STYLE_Normal], 1.0f, thing->fillcolor, thing->Translation, tex, fullbrightSprite); else args.SetStyle(thing->RenderStyle, thing->Alpha, thing->fillcolor, thing->Translation, tex, fullbrightSprite); args.SetDepthTest(true); args.SetWriteDepth(false); args.SetWriteStencil(false); PolyTriangleDrawer::DrawArray(thread->DrawQueue, args, vertices, 4, PolyDrawMode::TriangleFan); }